- JavaScript-this
JavaScript-this 分享 最近又在this的指向中迷惑了,虽然之前学过一次,丝毫不影响再次掉坑,这次又捋了一遍,加深影响! 其实在javascript中this的指向主要有四种 默认绑定(全局对象 严格模式下为undefined) 隐式绑定(谁调用this指向谁) 显示绑定(call bind apply) new绑定 ! 而在箭头函数里面,这四种都不适合,因为ES6规定箭头函数是没有this的,所以它只能继承,继承外层作用域中的this,也就是要看箭头函数所定义使用的地方(宿主对象)。 网上找了好多this指向的资料,个人觉得这两个总结得很好,大家可以看一下,结合两篇文章,相信大家对this得指向问题会更加清晰。 js 中的this,默认绑定、隐式绑定、显式绑定、new绑定、箭头函数绑定详解_toforu.com-CSDN博客 ①this指向四种:默认,隐式,显示call apply bind,new构造函数②优先级③new构造函数有无return④new做了什么⑤严格模式指向_lazylYYY的博客-CSDN博客 下面是阮一峰老师讲得this原理,大家也可以看一下! JavaScript 的 this 原理 - 阮一峰的网络日志 (ruanyifeng.com) Node中的this和浏览器中的this的区别 大家注意,虽然node和浏览器都是js的运行环境,但node中this和浏览器中的this还是稍有不同的 浏览器中的全局对象是window,node的全局对象是global 浏览器最外层的的this是windows,而node中最外层的this并不是全局对象global,而是module.export [代码]//在node环境下 console.log(this==global) //false console.log(this==module.exports) //true this.a=1; console.log(module.exports.a) //1 b=2; //不用var声明的变量 默认作为全局对象的属性 [代码] module.export是es6实现模块化的新特性,大家有兴趣可以了解一下。 vue中的this 在vue中的this,其实在vue的设计转化下,this一般指向vue实例 在Vue所有的生命周期钩子方法(created,mounted等等)和普通方法(method里面定义),this指向调用它的vue实例 其他情况可以参考js的this指向 作用域和原型的区别 当访问某个变量是,就是要通过作用域链去查找了,而访问某个对象的属性时,这个时候就时要通过原型链去找了了。 这其实也是有关变量和属性的区别,变量是属于作用域的范畴,而属性其实应该是属于原型的范畴 当我们定义一个变量是,比如 var a=1;其实a不是this里面的属性,a只是一个变量。 变量和属性一个很大的区别就是,属性可以删除,而变量不可以 [代码]var a=1; this.b=2; delete a; //false delete this.b ;//true [代码]
2021-11-22 - 云开发短信跳小程序(自定义开发版)教程
写在前面如果你想要自主开发,但没有云开发相关经验,可以采用演示视频来学习本教程: [视频] 一、能力介绍境内非个人主体的认证的小程序,开通静态网站后,可以免鉴权下发支持跳转到相应小程序的短信。短信中会包含支持在微信内或微信外打开的静态网站链接,用户打开页面后可一键跳转至你的小程序。 这个链接的网页在外部浏览器是通过 URL Scheme 的方式来拉起微信打开主体小程序的。 总之,短信跳转能力的实现分为两个步骤,「配置拉起网页」和「发送短信」。本教程将介绍如何执行操作完成短信跳转小程序的能力。 如果你想要无需写代码就能完成短信跳转小程序的能力,可以参照无代码版教程进行逐步实现。 二、操作指引1、网页创建首先我们需要构建一个基础的网页应用,在任何代码编辑器创建一个 html 文件,在教程这里命名为 index.html 在这个 html 文件中输入如下代码,并根据注释提示更换自己的信息: window.onload = function(){ window.web2weapp.init({ appId: 'wx999999', //替换为自己小程序的AppID gh_ID: 'gh_999999',//替换为自己小程序的原始ID env_ID: 'tcb-env',//替换小程序底下云开发环境ID function: { name:'openMini',//提供UrlScheme服务的云函数名称 data:{} //向这个云函数中传入的自定义参数 }, path: 'pages/index/index.html' //打开小程序时的路径 }) } 以上引入的 web2weapp.js 文件是教程封装的有关拉起微信小程序的极简应用,我们直接引用即可轻松使用。 如果你想进一步学习和修改其中的一些WEB展示信息,可以前往 github 获取源码并做修改。 有关于网页拉起小程序的更多信息可以访问官方文档 如果你只想体验短信跳转功能,在执行完上述文件创建操作后,继续以下步骤。 2、创建服务云函数在上面创建网页的过程中,需要填写一个UrlScheme服务云函数。这个云函数主要用来调用微信服务端能力,获取对应的Scheme信息返回给调用前端。 我们在示例中填写的是 openMini 这个命名的云函数。 我们前往微信开发者工具,定位对应的云开发环境,创建一个云函数,名称叫做 openMini 。 在云函数目录中 index.js 文件替换输入以下代码: const cloud = require('wx-server-sdk') cloud.init() exports.main = async (event, context) => { return cloud.openapi.urlscheme.generate({ jumpWxa: { path: '', // 打开小程序时访问路径,为空则会进入主页 query: '',// 可以使用 event 传入的数据制作特定参数,无需求则为空 }, isExpire: true, //是否到期失效,如果为true需要填写到期时间,默认false expire_time: Math.round(new Date().getTime()/1000) + 3600 //我们设置为当前时间3600秒后,也就是1小时后失效 //无需求可以去掉这两个参数(isExpire,expire_time) }) } 保存代码后,在 index.js 右键,选择增量更新文件即可更新成功。 接下来,我们需要开启云函数的未登录访问权限。进入小程序云开发控制台,转到设置-权限设置,找到下方未登录,选择上几步我们统一操作的那个云开发环境(注意:第一步配置的云开发环境和云函数所在的环境,还有此步操作的环境要一致),勾选打开未登录 [图片] 接下来,前往云函数控制台,点击云函数权限,安全规则最后的修改,在弹出框中按如下配置: [图片] 3、本地测试我们在本地浏览器打开第一步创建的 index.html ;唤出控制台,如果效果如下图则证明成功! 需要注意,此处本地打开需要时HTTP协议,建议使用live server等扩展打开。不要直接在资源管理器打开到浏览器,会有跨域的问题! [图片] 4、上传本地创建好的 index.html 至静态网站托管将本地创建好的 index.html 上传至静态网站托管,在这里静态托管需要是小程序本身的云开发环境里的静态托管。 如果你上传至其他静态托管或者是服务器,你仍然可以使用外部浏览器拉起小程序的能力,但会丧失在微信浏览器用开放标签拉起小程序的功能,也不会享受到云开发短信发送跳转链接的能力。 如果你的目标小程序底下有多个云开发环境,则不需要保证云函数和静态托管在一个环境中,无所谓。 比如你有A、B两个环境,A部署了上述的云函数,但是把 index.html 部署到B的环境静态托管中了,这个是没问题的,符合各项能力要求。只需要保证第一步 index.html 网页中的云开发环境配置是云函数所在环境即可。 部署成功后,你便可以访问静态托管的所在地址了,可以通过手机外部浏览器以及微信内部浏览器测试打开小程序的能力了。 5、短信发送云函数的配置在上面创建 openMini 云函数的环境中再来一个云函数,名字叫 sendsms 。 在此云函数 index.js 中配置如下代码: const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event, context) => { try { const config = { env: event.env, content: event.content ? event.content : '发布了短信跳转小程序的新能力', path: event.path, phoneNumberList: event.number } const result = await cloud.openapi.cloudbase.sendSms(config) return result } catch (err) { return err } } 保存代码后,在 index.js 右键,选择增量更新文件即可更新成功。 6、测试短信发送能力在小程序代码中,在 app.js 初始化云开发后,调用云函数,示例代码如下: App({ onLaunch: function () { wx.cloud.init({ env:"tcb-env", //短信云函数所在环境ID traceUser: true }) wx.cloud.callFunction({ name:'sendsms', data:{ "env": "tcb-env",//网页上传的静态托管的环境ID "path":"/index.html",//上传的网页相对根目录的地址,如果是根目录则为/index.html "number":[ "+8616599997777" //你要发送短信的目标手机,前面需要添加「+86」 ] },success(res){ console.log(res) } }) } }) 重新编译运行后,在控制台中看到如下输出,即为测试成功: [图片] 你会在发送的目标手机中收到短信,因为短信中包含「退订回复T」字段,可能会触发手机的自动拦截机制,需要手动在拦截短信中查看。 需要注意:你可以把短信云函数和URLScheme云函数分别放置在不同云开发环境中,但必须保证所放置的云开发环境属于你操作的小程序 另外,出于防止滥用考虑,短信发送的云调用能力需要真实小程序用户访问才可以生效,你不能使用云端测试、云开发JS-SDK以及其他非wx.cloud调用方式(微信侧WEB-SDK除外),会提示如下错误: [图片] 如果你想在其他处使用此能力,可以使用服务端API来做正常HTTP调用,具体访问官方文档 7、查看短信监控图表进入 云开发控制台 > 运营分析 > 监控图表 > 短信监控,即可查看短信监控曲线图、短信发送记录。 [图片] 三、总结短信跳转小程序核心是静态网站中配置的可跳转网页,外部浏览器通过URL Scheme 来实现的,这个方式不适用于微信浏览器,需要使用开放标签才可以URL Scheme的生成是云调用能力,需要是目标小程序的云开发环境的云函数中使用才可以。并且生成的URL Scheme只能是自己小程序的打开链接,不能是任意小程序(和开放标签的任意不一致)短信发送能力的体验是每个有免费配额的环境首月100条,如有超过额度的需求可前往开发者工具-云开发控制台-对应按量付费环境-资源包-短信资源包,进行购买。如当前资源包无法满足需求也可通过云开发 工单 提交申请[图片]短信发送也是云调用能力,需要真实小程序用户调用才可以正常触发,其他方式均报错返回参数错误,出于防止滥用考虑云函数和网页的放置可以不在同一个环境中,只需要保证所属小程序一致即可。(需要保证对应环境ID都能接通)如果你不需要短信能力,可以忽略最后两个步骤CMS配置渠道投放、数据统计可参考官方文档
2021-04-07 - MYSQL笔记
创建数据库 指令规范 注意:从现在开始将会频繁使用mysql指令,需要遵守一些指令规范 除use database指令外,其他指令都需要在结尾加上分号’;’ 使用英文的标点符号 数据库命名规则一般以小写英语字母和_组成 数据表命名是小写字母和下划线 [代码]_[代码] 组成,用来分割不同单词之间的含义 各功能指令 查看数据库 [代码]>show databases; [代码] 系统会显示当前已经存在四个MySQL系统数据库,这些数据库用来存储和管理 MySQL 服务相关的一些配置。 新建数据库 [代码]>create database item_name; [代码] 也可以利用客户端工具新建数据库 此处略. 删除数据库 在登录状态下,输入指令: [代码]>drop database item_name; [代码] 选中数据库 输入选择数据库指令: [代码]>use item_name; [代码] 选中数据后才能对数据库进行操作,当想选中另一个数据库时,直接输入use database_name即可 设计数据表 一个数据表主要包含信息有 : 表名、主键、字段、数据类型、索引 数据表是在数据中进行操作的,所以进行数据表操作时,需要先进入相对应的数据库 字段 以数据表student为例: 字段名称 数据类型 含义 id 无符号整型 (unsigned int) 自增子健 name varchar(50) 学生姓名 age unsigned int 学生年龄 id_number varchar(18) 身份证号 主键 每一张表都必须有一个主键,一般建议选定为无符号整型 id 作为主键,并且 id 一般作为主键一般设置为自增的(特殊情况可使用其他非自增 id 作为主键) 新建数据表 学生数据表 [代码]create table `student` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '无名', `age` int(10) UNSIGNED NOT NULL DEFAULT 0, `id_number` varchar(18) NOT NULL DEFAULT '', PRIMARY KEY (`id`) ); [代码] 注:其中 “student” 为表名称,“id”、“name”、“age”、“id_number” 为字段名称,跟在字段名称后面的是字段的数据类型,“UNSIGNED” 表示无符号,“AUTO_INCREMENT” 表示自增,"PRIMARY KEY ([代码]id[代码])"表示设置 “id” 为业务主键,,"NOT NULL DEFAULT ‘无名’ " 表示默认不为空,且默认值为 “无名” 。 同理: 教师数据表 [代码]create table `teacher` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '教师名', `age` int(10) UNSIGNED NOT NULL DEFAULT 0, `id_number` varchar(18) NOT NULL DEFAULT '', PRIMARY KEY (`id`) ); [代码] 课程表 [代码]create table `course` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `course_name` varchar(50) NOT NULL DEFAULT '', `teacher_id` int(10) UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (`id`) ); [代码] 学生选课关联表 [代码]create table `student_course` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `student_id` int(10) UNSIGNED NOT NULL DEFAULT 0, `course_id` int(10) UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (`id`) ); [代码] 查看数据表 输入查看指令: [代码]show tables; [代码] 可查看到新建了四个数据表. 数据表设计规范 第一设计范式 第一设计范式要求表中字段都是不可再分的,如果实体中的某个属性有多个值时,必须拆分为不同的属性 。通俗理解即一个字段只存储一项信息. 第二设计范式 第二设计范式要求表中必须存在业务主键,并且全部非主键依赖于业务主键。 第三设计范式 一个数据库表中不包含已在其它表中已包含的非主键字段。就是说表的信息如果能够被推导出来,就不应该单独的设计一个字段来存放(能尽量外键 join 就用外键 join)。 反范式设计 没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,提高读性能,就必须降低范式标准,适当保留冗余数据。具体做法是: 在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,减少了查询时的关联,提高查询效率,因为在数据库的操作中查询的比例要远远大于 DML 的比例。 alter 命令修改表 修改数据表名称 [代码]alter table 旧的表名 rename to 新的表名; [代码] 查看建表sql语句 [代码]show create table 需要查看的表名; [代码] 修改建表sql语句 [代码]alter table `表名` modify column `字段1` 数据类型 新字段类型的字符集和编排方式 not NULL default '无名' after `字段2`; [代码] 新增表字段 [代码]alter table `表名` add column `新字段` 数据类型 not NULL default 1 comment '字段名 : 1:数据一 2:数据二' alter `字段2`; [代码] 其中comment '字段名 : 1:数据一 2:数据二’表示该字段的注释说明 删除表字段 [代码]alter table `表名` drop column `字段`; [代码] 修改表字段名称 [代码]alter table `表名` change column `旧字段名` `新字段名` 数据类型 编码方式 [代码] 删除数据表 先选中表所在的数据库,然后输入删除指令: [代码]use 数据库; drop table 表名; [代码] insert 插入数据 [代码]insert into 表名 (字段_1,字段_2,字段_3...) values (数据,数据,数据...), (数据,数据,数据...), ... (数据,数据,数据...); [代码] 通过使用真实数据替换上面指令,可进行一条至多条数据的插入. delete删除数据 删除部分数据 [代码]delete from 表名 where 字段=1(假设为1); [代码] 选中数据库,然后输入上面指令表明:删除所选表中,所选字段对应数据为1的数据. 删除表全部数据 delete [代码]delete from 表名; [代码] truncate [代码]truncate table 表名; [代码] 注: TRUNCATE 清空表数据的实际过程是先删除数据表,然后新建一张和原来表结构一模一样的表来替代清空。 DELETE 删除表数据不会改变自增主键的增长值 select查询数据 查询表中所有的数据 [代码]select * from 表名; [代码] 查询指定条数的结果集 [代码]select * from 表名 limit 10(假设为10); [代码] 输入上述指令将呈现10条结果的结果集. 查询指定其实条数的结果集 [代码]select * from 表名 limit 10,10;(假设为10,10); [代码] 将输出11-20的十条结果的结果集. 查询指定字段列的结果集 输入以下指令: [代码]select 字段1,字段2 from 表名 limit 6,5; [代码] 给指定字段重命名 [代码]select 字段1 as 字段3,字段2 from 表名 limlt 6,5; [代码] 注:该重命名仅仅使用呈现结果,而不会保存到原数据表 update更新数据 更新某一列字段的值 输入下列指令: [代码]update 表名 set 字段1=数据1 limit 3; [代码] 即可将前三条数据中字段1的数据修改为 数据1. 更新多段字段的值 [代码]update 表名 set 字段1=数据1,字段2=数据2 where 某字段=某一数据; [代码] 即可进行修改. like模糊查询 模糊查询表达式 [代码]%[代码] 表示指代任意内容,例如 [代码]'%小%'[代码] 表示包含 [代码]小[代码] 的表达式,且 [代码]小[代码] 前后都有内容, [代码]'%小'[代码] 表示以 [代码]小[代码] 结尾的表达式,[代码]王[代码] 前面有内容,后面没有内容,[代码]'小%'[代码] 表示以 [代码]小[代码] 开头的表达式,[代码]小[代码] 前面没有内容,后面有内容。 使用like模糊查询 输入下面指令: [代码]select * from 表名 where 某字段 like '小%'; [代码] 即可查看该字段对应的字符串最右边的字符为’小’的结果. where条件查询 where条件 符号 说明 < 小于 = 等于 > 大于 <>或!= 不等于 <= 小于等于 >= 大于等于 like 模糊条件 not like 不符合模糊条件 between and 在两个值之间(包含两端值) not between and 不在在两个值之间(不包含两端值) is null 空 is not null 不为空 单条件查询 [代码]select * from 表名 where 条件1; [代码] and多条件查询 [代码]select * from 表名 where 条件1 and 条件2; [代码] and表示同时满足两个条件才为真. or多条件查询 [代码]select * from 表名 where 条件1 or 条件2; [代码] 只需要满足至少一个条件即为真 union联合查询 union all查询 输入以下指令即可把满足两种查询条件的结果集并到一起: [代码]select * from 表名 where 条件1 union all select * from 表名 where 条件2; [代码] 注: [代码]UNION ALL[代码] 联合查询的结果集没有去掉重复的数据. union查询 [代码]select * from 表名 where 条件1 union select * from 表名 where 条件2; [代码] 注:[代码]UNION[代码] 将两种查询结果并到一起,可以看到结果集中已经去掉重复的数据 order by排序 ASC 从小到大排序 输入以下指令: [代码]select * from 表名 order by 某字段 ASC; [代码] 即可根据该字段数据实现从小到大排序 DESC 从大到小排序 [代码]select * from 表名 order by 某字段 DESC; [代码] 多字段混合排序 [代码]select * from 表名 order by 字段1 DESC,字段2 ASC; [代码] 根据优先级是:先进行根据字段1的降序,在此基础上再进行根据字段2的升序. 对字符串排序 对字符串排序和对数值进行排序的区别在于:英文字符排序在前,中文在后,其中排序规则是按照字符 ASCII码 对应值的大小排序. join表连接 left左连接 输入以下指令: [代码]select a.原字段名 as 新字段名,a.*,b.* from 表一 a left join 表二 b on a.字段1=b.字段2; [代码] [代码]a.*[代码] 表示 [代码]表一[代码]所有字段数据; [代码]t.*[代码] 表示 [代码]表二[代码] 表字段所有数据; [代码]ON[代码] 后面跟着的条件是连接表的条件; [代码]表一 a[代码] 表示将 [代码]表一[代码] 简写为 [代码]a[代码], [代码]表二 b[代码] 表示将 [代码]表二[代码] 简写为 [代码]b[代码]; [代码]left join[代码] 为左连接,是以左边的表为’基准’,若右表没有对应的值,用 [代码]NULL[代码] 来填补。 同理: [代码]right join[代码] 为右连接,是以右边的表为’基准’,若左表没有对应的值,用 [代码]NULL[代码] 来填补。 当然,内连接有些许不同: [代码]INNER JOIN[代码] 为内连接,展示的是左右两表都有对应的数据。 多表混合连接 即一或多种连接方式的多次使用: [代码]select a.原字段名 as 新字段名,a.*,b.* from 表一 a left join 表二 b on a.字段1=b.字段2 right join 表三 c on b.字段2=c.字段3 inner join 表四 d on b.字段3=d.字段4; [代码] 该多表连接以表二的字段2为基准. distinct去重 输入下列指令: [代码]select distinct 字段1,字段2,...字段n from 表一 a inner join 表二 b on a.字段1=b.字段2; [代码] group by分组 单字段分组 输入以下指令: [代码]select a.原字段名 as 新字段名,a.*,b.* from 表一 a left join 表二 b on a.字段1=b.字段2 right join 表三 c on b.字段2=c.字段3 inner join 表四 d on b.字段3=d.字段4 group by 某字段; [代码] 即可完成单字段分组. 多字段分组 输入以下指令: [代码]select a.原字段名 as 新字段名,a.*,b.* from 表一 a left join 表二 b on a.字段1=b.字段2 right join 表三 c on b.字段2=c.字段3 inner join 表四 d on b.字段3=d.字段4 group by a.字段1,b.字段2; [代码] 即可完成所需分组. 单字段分组和多字段分组的区别在于,单字段是以一个字段来判断数据是否重复分组出来的结果,多字段分组是以多个字段同时来判断是否重复分组出来的结果。 聚合函数 函数 作用 avg() 计算平均值 sum() 计算总和 count() 计算总条数 min() 取最小值 max() 取最大值 数据类型 整数类型 类型 大小 说明 tinyint 1字节 小整型 smallint 2字节 小整型 mediumint 3字节 中整型 int 4字节 整型 bigint 8字节 大整型 浮点类型 类型 大小 说明 float 4字节 单精度浮点型 double 8字节 双精度浮点型 decimal 每4个字节存储9个数字,小数点占1字节 精确类型,常用来表示金额 日期与时间类型 类型 大小 格式 范围 date 3字节 YYYY-MM-DD 1000-01-01~9999-12-31 time 3-6字节 HH::MM::SS[.微秒] -838:59:59~838:59:59 year 1字节 YYYY 1901~2155 datetime 5-8字节 YYYY-MM-DD HH::MM::SS[.微秒] 1000-01-01 00:00:00~2038-01-19 03:14:07 UTC timestamp 4-7字节 YYYY-MM-DD HH::MM::SS[.微秒] 1974-01-01 00:00:00~2038-01-19 03:14:07 UTC 字符串类型 类型 范围 说明 char 1~255个字节 固定长度 varchar 字段存储所占字节数不能超过65535字节 可变长度 tinytest 最大长度255字节 可变长度 text 最大长度65535字节 可变字节 mediumtext 最大字节16777215字节 可变字节 longtext 最大长度4294967295字节 可变字节 char 类型是一种固定长度的类型,varchar 则是一种可变长度的类型,它们的区别是:char(M) 类型的数据列里,每个值都占用 M 个字节,如果某个长度小于 M,MySQL 就会在它的右边用空格字符补足.。 枚举值类型 类型 范围 说明 enum 几何数最大65535 枚举值类型,只能插入列表中指定的值 二进制类型 类型 范围 说明 tinyblob 最大长度255字节 可变长度 blob 最大长度65535字节 可变长度 mediumblob 最大长度16777215字节 可变长度 longblob 最大长度4294967295字节 可变字节 如果觉得对你们有帮助,可以给文章点个赞哦~ [图片]
2021-11-17 - 技术文章写作规范
技术文章写作规范 来源: GitHub - ruanyf/document-style-guide: 中文技术文档的写作规范,by阮一峰 前言 最近在写文章会想一篇好的文章是不是和写语文作文一样有规范呢?所以就在网上看到阮一峰老师的写的这篇中文技术文档写作规范,觉得真的写得很好,这里就和大家分享一下。 但是阮老师写的是技术文档规范,个人觉得文章的话如果整得太严肃的话或许不太好,不过一些结构,表达还是要注意得,像代码用 md 代码块, uml 图等等会好一点,当然这是个人爱好,这里给大家转载一些我觉得在平时写文章要注意一下的几个点,有兴趣的可以直接去看阮老师的正文! 标题 层级 标题分为四级。 一级标题:文章的标题 二级标题:文章主要部分的大标题 三级标题:二级标题下面一级的小标题 四级标题:三级标题下面某一方面的小标题 下面是示例。 [代码]# 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 [代码] 原则 (1)一级标题下,不能直接出现三级标题。 示例:下面的文章结构,缺少二级标题。 [代码]# 一级标题 ### 三级标题 [代码] (2)标题要避免孤立编号(即同级标题只有一个)。 示例:下面的文章结构,[代码]二级标题 A[代码]只包含一个三级标题,完全可以省略[代码]三级标题 A[代码]。 [代码]## 二级标题 A ### 三级标题 A ## 二级标题 B [代码] (3)下级标题不重复上一级标题的名字。 示例:下面的文章结构,二级标题与下属的三级标题同名,建议避免。 [代码]## 概述 ### 概述 [代码] (4)谨慎使用四级标题,尽量避免出现,保持层级的简单,防止出现过于复杂的章节。 如果三级标题下有并列性的内容,建议只使用项目列表(Item list)。 示例:下面的结构二要好于结构一。结构一适用的场景,主要是较长篇幅的内容。 [代码]结构一 ### 三级标题 #### 四级标题 A #### 四级标题 B #### 四级标题 C 结构二 ### 三级标题 **(1)A** **(2)B** **(3)C** [代码] 文本 字间距 (1)全角中文字符与半角英文字符之间,应有一个半角空格。 [代码]错误:本文介绍如何快速启动Windows系统。 正确:本文介绍如何快速启动 Windows 系统。 [代码] (2)全角中文字符与半角阿拉伯数字之间,有没有半角空格都可,但必须保证风格统一,不能两种风格混杂。 [代码]正确:2011年5月15日,我订购了5台笔记本电脑与10台平板电脑。 正确:2011 年 5 月 15 日,我订购了 5 台笔记本电脑与 10 台平板电脑。 [代码] 半角的百分号,视同阿拉伯数字。 [代码]正确:今年我国经济增长率是6.5%。 正确:今年我国经济增长率是 6.5%。 [代码] (3)英文单位若不翻译,单位前的阿拉伯数字与单位符号之间,应留出适当的空隙。 [代码]例1:一部容量为 16 GB 的智能手机 例2:1 h = 60 min = 3,600 s [代码] (4)半角英文字符和半角阿拉伯数字,与全角标点符号之间不留空格。 [代码]错误:他的电脑是 MacBook Air 。 正确:他的电脑是 MacBook Air。 [代码] 句子 (1)避免使用长句。 不包含任何标点符号的单个句子,或者以逗号分隔的句子构件,长度尽量保持在 20 个字以内;20~29 个字的句子,可以接受;30~39 个字的句子,语义必须明确,才能接受;多于 40 个字的句子,任何情况下都不能接受。 [代码]错误:本产品适用于从由一台服务器进行动作控制的单一节点结构到由多台服务器进行动作控制的并行处理程序结构等多种体系结构。 正确:本产品适用于多种体系结构。无论是由一台服务器(单一节点结构),还是由多台服务器(并行处理结构)进行动作控制,均可以使用本产品。 [代码] 逗号分割的长句,总长度不应该超过 100 字或者正文的 3 行。 (2)尽量使用简单句和并列句,避免使用复合句。 [代码]并列句:他昨天生病了,没有参加会议。 复合句:那个昨天生病的人没有参加会议。 [代码] (3)同样一个意思,尽量使用肯定句表达,不使用否定句表达。 [代码]错误:请确认没有接通装置的电源。 正确:请确认装置的电源已关闭。 [代码] (4)避免使用双重否定句。 [代码]错误:没有删除权限的用户,不能删除此文件。 正确:用户必须拥有删除权限,才能删除此文件。 [代码] 变化程度的表示法 数字的增加要使用“增加了”、“增加到”。“了”表示增量,“到”表示定量。 [代码]增加到过去的两倍 (过去为一,现在为二) 增加了两倍 (过去为一,现在为三) [代码] 数字的减少要使用“降低了”、“降低到”。“了”表示增量,“到”表示定量。 [代码]降低到百分之八十 (定额是一百,现在是八十) 降低了百分之八十 (原来是一百,现在是二十) [代码] 不能用“降低 N 倍”或“减少 N 倍”的表示法,要用“降低百分之几”或“减少百分之几”。因为减少(或降低)一倍表示数值原来为一百,现在等于零。 参考链接 产品手册中文写作规范, by 华为 写作规范和格式规范, by DaoCloud 技术写作技巧在日汉翻译中的应用, by 刘方 简体中文规范指南, by lengoo 文档风格指南, by LeanCloud 豌豆荚文案风格指南, by 豌豆荚 中文文案排版指北, by sparanoid 中文排版需求, by W3C 为什么文件名要小写?, by 阮一峰 Google Developer Documentation Style Guide, by Google
2021-11-18 - 微信小程序开发-将数据写入全局数据
微信小程序的全局数据写在 [代码]app.js[代码]中,需要现在里面声明存储数据的变量如下: [代码]//app.js this.globalData = {} this.userInfo = {}//这个是我们。等下要用到的变量// this.userMessage = [] [代码] 然后在需要使用以上声明的全局变量的时候声明一下: [代码]const app = getApp()//这个声明是为了后面调用的方便 [代码] 然后使用[代码]Object.assign()[代码]将数据拷贝到全局变量中。 注:[代码]Object.assign()[代码]用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 [代码]Object.assign( app.userInfo , res.data ); [代码] 此时res.data中的数据已经传输到全局变量中。在其他页面使用使用[代码]getApp()[代码]即可调用。
2021-11-16 - 实战——使用云函数(一)小程序与云函数的参数传递
建立环境 首先需要在project.config.json 文件,新增 cloudfunctionRoot 字段 { “cloudfunctionRoot”: “cloudfunctions/” } 接着:右键当前环境,选择新建 Node.js 函数,这里我们将云函数命名为 todo_functions [图片] [代码]可以看到其内部有一个模板 // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() return { event, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, } } [代码] 其中上面的 exports.main = async (event, context) 中event 对象中含有——调用时传输的参数、openid、appid 小程序中调用云函数 如何在js中调用云函数: [代码]wx.cloud.callFunction({ // 云函数名称 name: 'todo_functions', // 传给云函数的参数 data: { name:"world !!!" }, success: function(res) { console.log(res.result.new_name) // hello world !!! }, fail: console.error }) [代码] 云函数中的接收参数 在云函数中接收js传来的参数,并返回参数: [代码]exports.main = async (event, context) => { return { new_name: "hello " + event.name // 接收来自js的参数name,返回新的返回值new_name } } [代码] 记得写好云函数后,要记得上传哦!(右键函数,选择上传并部署:云端安装依赖) [图片] 总结 好了,到现在的我们,我们完成了云函数与小程序的参数传递,小程序调用函数wx.cloud.callFunction,把参数 name 写道data中,将数据传到云函数 todo_functions,接着云函数通过event接收到来在小程序的参数,event.name可以获取到参数,接着小程序通过success,可以接收到云函数成功调用后返回的new_name, res.result.new_name。 [图片]
2021-11-18 - camera组件修改形状与人脸识别
产品需求 1.小程序需要用户上传人脸照片供公司设备使用; ui设计图如下 [图片] 整理思路 1.小程序无法使用sdk进行实时人脸识别,故使用camera每隔数秒截取一张用户照片,使用第三方api检测人脸是否符合要求; 2.camera组件css设置border-radius真机无效,故使用一张扣出透明圆形图片覆盖camera组件,达到原型取景框的样式,图片如下: [图片][图片] 总结 1.人脸识别审核通过不了,没有相关类目无法通过审核; [图片] 2.camera组件拍摄的照片像素等于camera设置的组件宽高;
2021-08-24 - 写小程序没有灵感?可以看看这几个小程序和网站
1、https://www.egouz.com/xcx/ https://www.w3cschool.cn/miniapp# [图片] 这个网站中含有一些近期比较热门的小程序,比如像工具类的小程序 2、阿拉丁指数行业洞察平台 [图片] [图片] 这个阿拉丁指数可以很好地帮助快速了解近期的小程序情况~ 3、微信指数 [图片] [图片][图片] 这个官方小程序,很好的反应了近期的一些热点搜索词,可以很好解决命名问题~ 4、就是微信的关键词下显示的100+和1000+,也可以很好地反映了近三天的热点~ [图片]
2021-11-18 - 分享几个最近访问100+的有趣小程序
1、下一个假期 这个小程序能够帮助你查看下一个假期的时间,十分方便 [图片] [图片] 2、潮汐睡眠 如果平时睡不着的话,也可以听一听,放松一下,有助于睡眠 [图片]、 [图片] 3、人生进度 看完这个小程序,不由为时间做好了规划~ [图片] [图片]
2021-11-19 - 从零开始学小程序
收获 可以成功制作出来一个天气预报!不过还是有很多的缺陷,毕竟视频中代码补全。 了解到了wxml+wxss,感觉这两个就是前端里面的html+css。 懂得如何制作跳转页面,以及第二页面的默认显示。 <view> [代码]<view></view>[代码]这个就是最简单的制作啦!在这两个中间输入你想要输入的东西就可以显示出来而且还会自动换行 [代码]class = "内容"[代码] 这个内容就类似于一个标记可以用在每个标签里面,例如 [代码]<view class = "内容">[代码] 就相当于给这个标签一个命名,然后可以在wxss里面使用[代码].内容 { }[代码]在大括号里面对标签的修饰,例如它的宽,高,距离顶部距离等等的作用。 [代码]{{ }}[代码] 两个大括号的使用,就是显示内容的一个动态切换吧,感觉来说,就是在js里面对括号里面的内容根据需要切换 [代码]bindtap="命名"[代码]监听器对用户的点击作出对应的行为。对应的行为需要自己在js文件里面实现,通过命名来对bindtap行为作出的响应。 <image src = “”> src里面输入的就是你的项目里面有的图片,就是需要自己把图片放进去,然后用路径表达去选择图片啦! <scroll-view scroll-x> 实现**横轴(X轴方向)**的滚动,这个是用于[代码]<view wx:for="">[代码]而[代码]wx:for[代码]就是一个循环,将需要的内容循环输出,当wxss里面对该view设置了[代码]flex-shrink: 0; /* 确保距离不会被缩小,不会被自适应 */[代码]就当超出屏幕显示宽度的时候后面的内容将被覆盖不会显示出来,就需要使用[代码]<scroll-view>[代码]来用横向滑动显示出来! const dayMap = [] Map这里就是映射,一对一映射,就相当于 x = y,找到这个x输出y。 编译页面 “添加编译模式”里面修改启动页面就可以编译的时候直接显示你想要编译显示出来的那个页面 用户响应以及用户触碰响应范围 我们可以通过[代码]<view class = "">省略号</view>[代码]对里面的内容进行一个扩大的包裹,让用户可以选择的地方大一些。可以有[代码]wx.showToast({})[代码]进行显示例如成功或者失败的提示。 页面跳转 利用[代码]bindtap[代码] 和js里的[代码]wx.navigateTo({url:''})[代码]进行页面的跳转 第二页面的[代码]onLoad(options)[代码]这里面的options是第一个页面中跳转url里面添加的[代码]'……?city=' + this.data.city[代码] 其中options就显示内容为对应的city=第一个界面里面的city 部分内容的切换 当我们获取到的只有名称不包括后缀名的时候,我们利用[代码]nowWeatherLogo: '/images/' + code + '@1x.png'[代码]类似于这样的 code表示获取的内容,可以通过+的方式把他们连接在一起并返回到wxml里面选择的图片资源路径。依次类推,当只有部分内容改动的时候,只需要用"+"把他们连接在一起就好了,不改动的内容用单引号引起来。 微信获取地址 [代码]wx.getLocation[代码] 获取用户所在地址 [代码]wx.getSetting[代码]当用户第一次选择取消的时候,第二次点击不应该没有响应,需要重新进入设置来让用户同意使用。 学习中遇到的问题以及解决方法 视频中的api无法使用以及没有提供的icon api的话我是用了心知天气来解决的,对于图标也有对应的,只是有的图标是白色在白的地方就像是没有图片显示一样。如果需要别的icon可以在iconfont上面寻找! 不在以下request合法域名列表中 这个得要在小程序“开发管理”->“开发设置”的服务器域名进行修改,使用外部链接的时候要加上“https://mp.weixin.qq.com”这个,手机预览才可以显示出来,我也不知道为什么。 视频中的不足 我觉得英文版的还挺好,起码是教项目入手,如果有中文字幕就更好了,不过英文来说大部分还是能懂。 前面五节都很好,但是到了第六节,它显示出来的页面每次都不一样,内容也是。 视频中没有对应的图标以及api提供,导致花费大部分时间在找图标什么的。 目前仍有不懂的地方 对于外部链接为什么在配置"request合法域名"中添加多一个“https://mp.weixin.qq.com”才可以在手机中预览正常使用? 对于纯白的图片,有没有方法可以让图片显示出来,就修改图片显示样式里面更改这个颜色,而不是一个一个图标的去修改? 如果不能修改图标怎么能够修改背景颜色,因为只是在view包括的内容那一段里面使用[代码]background-color[代码]去设置背景颜色会发现不是整个背景,而是一部分,只是一个容器那样会有边界的。 [代码]TypeError: Cannot read property '0' of undefined[代码] 是因为第二个页面没有获取到第一个页面的city才会显示出这个么?(直接编译显示第二个界面) [代码]onLoad(options) { // console.log(options); this.setData({ city: options.city }); this.getWeekWeather() } [代码] [代码] getWeekWeather(callback) { wx.request({ url: 'https://api.seniverse.com/v3/weather/daily.json', success: res => { let result = res.data.results[0] /* ←出错的行数*/ this.setWeekWeather(result) }, [代码]
2021-11-16 - 学习笔记(自用)
变量 存储/索引 声明 let/var/const 赋值 ‘=’ 数据类型 数字 字符串 ‘’ 数组[] 对象{} 条件语句 [代码]wx:if = "{{}}"[代码] 引号里面就是判断是真是假,真的就显示假的就不显示 [代码]wx:else[代码] 基础知识 [代码]wx:for = "{{ list }}"[代码] 后面只要涉及变量的都要加上[代码]item.[代码] [代码]wx:for-item = " course "[代码] 可以更改[代码]item[代码] 为 [代码]course[代码] for触发后是从数组第0个开始依次遍历完 [代码]{{ index }}[代码]索引,也可以理解为下标(一样可以像上面那样更改命名)、索引都是从0开始 [代码]wx:key = key[代码] 下面的警告用这个可以解决,是关于性能问题 [代码]for (初始化语句; 条件; 后执行语句) {执行语句}[代码] [代码]if(条件)[代码]。 [代码]=赋值[代码] 、[代码]== 判断[代码] 取子串:str用"substr",arr用"slice" 追加: str用"+", arr 用 “push” 前置:str用"+", arr用“unshift” 函数 [代码]function add() {函数体}[代码] 对于一个命名里面要加上括号才是函数,括号里的为参数 函数组成:关键字function、参数、返回值 在对象里面的function叫做方法不叫函数 例子: [代码]function add(a, b) { return a + b; } [代码] template 样板用于存储样式 [代码]<template name="course-card"> <view class="course-card"> <view> <image src="{{ course.coverPath }}" mode="widthFix"></image> </view> <view>{{ course.name }}</view> <view wx:if="{{ course.price > 0}}" class="price">{{ course.price }}</view> <view wx:else class="price">免费</view> </view> </template> [代码] [代码]<template is="course-card" data="{{course}}" />[代码] 这里没有[代码]</template>[代码] block 作用就是用于封装,可以把条件语句放进block标签里面,可以简化代码 [代码]<block wx:for="{{list}}" wx:key="key" wx:for-item="course"> </block>[代码] 最后最后!!一定要学会看文档
2021-11-18 - 爱迷彩服务小程序2.1.0版本(持续更新)---服务页面实现
服务页面实现截图如下 [图片] wxml文件 <view> <view> <view class="weui-search-bar"> <view class="weui-search-bar__form"> <!-- 搜索框 --> <view class="weui-search-bar__box"> <icon class="weui-icon-search_in-box" type="search" size="14"></icon> <input type="text" class="weui-search-bar__input" placeholder="请输入搜索内容"/> </view> </view> <!-- 搜索按钮,调用搜索查询方法 --> <view class="weui-search-bar__cancel-btn" bindtap='方法名a'>搜索</view> </view> </view> <view class='mowei'> <view class='wodedingdan'> <image src='../imag/fengche.png'></image> <view class='ziti'>战友动态</view> </view> <view class='wodedingdan'> <image src='../imag/location.png'></image> <view class='ziti'>附近战友</view> </view> <view class='wodedingdan'> <image src='../imag/club.png'></image> <view class='ziti'>战友部落</view> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/intnet.png"></image> <text class="txt1">互联网+创业项目</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/skills.png"></image> <text class="txt1">职业技能培训</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/policy.png"></image> <text class="txt1">政策解读通道</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/wangted.png"></image> <text class="txt1">就业招聘</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/imbark.png"></image> <text class="txt1">自主创业</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/commonwealth.png"></image> <text class="txt1">军旅公益</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/fund.png"></image> <text class="txt1">战友基金</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/league.png"></image> <text class="txt1">军盟</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/market.png"></image> <text class="txt1">战友商城</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> <view class="menu"> <view class="menu-child"> <image class="menu-image" src="../imag/soldier.png"></image> <text class="txt1">爱迷彩服务</text> <image class="right-arrow" src="../imag/right-arrow.png"></image> </view> </view> </view> wxss文件 .weui-search-bar { position: relative; padding: 8px 10px; display: -webkit-box; display: -webkit-flex; display: flex; box-sizing: border-box; background-color: #EFEFF4; border-top: 1rpx solid #D7D6DC; border-bottom: 1rpx solid #D7D6DC; } .weui-icon-search_in-box { position: absolute; left: 10px; top: 7px; } .weui-search-bar__form { position: relative; -webkit-box-flex: 1; -webkit-flex: auto; flex: auto; border-radius: 5px; background: #FFFFFF; border: 1rpx solid #E6E6EA; } .weui-search-bar__box { position: relative; padding-left: 30px; padding-right: 30px; width: 100%; box-sizing: border-box; z-index: 1; } .weui-search-bar__input { height: 28px; line-height: 28px; font-size: 14px; } .weui-search-bar__cancel-btn { margin-left: 10px; line-height: 28px; color: #09BB07; white-space: nowrap; } .mowei { display: flex; width: 100%; /* margin-left: 20rpx; margin-right: 20rpx; */ font-size: 32rpx; margin-top: 50rpx; } .wodedingdan { width: 130rpx; text-align: center; font-size: 13px; flex-grow: 1; /* 均匀分布属性 */ } .wodedingdan image { width: 70rpx; height: 70rpx; } .ziti { margin-top: 10rpx; } .menu { height: 40px; display: flex; align-items: center; margin-top: 7px; background-color: #EFEFF4; border-radius: 8px; position: relative; /*父元素设置为相对位置*/ } .right-arrow{ height: 18px; width: 18px; right: 15px; position: absolute; /*让图片靠右距离5px,子元素设置为position:absolute,父元素设置为position:relative*/ } .menu-image { width: 30px; height: 30px; margin: 4px; } .txt1 { align-items:center; margin-left: 5px; font-size: 12px; } .menu-child{ display: flex; flex-direction: row; align-items: center; justify-content: center; } 总结:用到的几个重要的属性 display:flex; 将对象作为弹性伸缩盒显示,无需考虑不同浏览的兼容问题。 flex-direction:row; 主轴为水平方向,起点在左端。 align-items:center; 定义项目在交叉轴上如何对齐,center表示中轴线对齐。 justify-content:cneter; 定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。 flex-grow:1; /*均匀分布*/ 动态点击事件等待后续更新完成,目前还在构思各个功能模块的页面,敬请等待,麻烦大家点赞收藏,给点意见,谢谢啦!
2021-11-18 - 微信登陆授权获取用户信息
微信登陆授权获取用户信息学习记录 wxml代码: <view wx:if="{{canIUse}}" class="mai"> <button class="but" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权登录</button> <view class="med">-----------·-----------</view> <view class="txt">\t\t欢迎使用小程序,我们需要一些您公开的信息,包括微信昵称,头像等等,请放心,我们会妥善保管您的信息!</view> </view> <view wx:else>请升级微信版本</view> js代码: Page({ data: { canIUse: wx.canIUse('button.open-type.getUserInfo') }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { //显示加载的图标 wx.showLoading({ title: '加载中', }) wx.login({ success(res){ if(res.code){ // //发起网络请求 // wx.request({ // url: 'https://test.com/onLogin', // data:{ // code:res.code // } // }) wx.getSetting({ success (res){ if (res.authSetting['scope.userInfo']) { // 已经授权,可以直接调用 getUserInfo 获取头像昵称 wx.getUserInfo({ success: function(res) { console.log(res.userInfo) getApp().globalData.userInfo = res.userInfo } }) } } }) }else { console.log('登陆失败' + res.errMsg) } } }) // 查看是否授权 setTimeout(function () { wx.hideLoading() },2000) }, bindGetUserInfo (e) { console.log(e.detail.userInfo) }, }) json代码: { "usingComponents": {}, "navigationBarBackgroundColor": "#F2F2F2", "navigationBarTitleText": "微信授权", "navigationBarTextStyle": "black" } wxss代码: /* pages/load/load.wxss */ .mai{ width: 80%; height: 300rpx; margin-top: 350rpx; margin-left: 10%; margin-right: 10%; } .but{ width: 70%; height: 80rpx; background-color: #04be01; border-radius: 10rpx; align-content: center; text-align: center; margin-left: 15%; margin-right: 15%; color: white; font-size: 37rpx; font-weight: bold; } .txt{ color: #8a8a8a; width: 92%; font-size: 32rpx; margin-top: 10rpx; margin: auto; font-weight: 10rpx; } .med{ color: #8a8a8a; font-size: 40rpx; text-align: center; margin-top: 20rpx; }
2021-11-16 - [有点炫]自定义navigate+分包+自定义tabbar
自定义navigate+分包+自定义tabbar,有需要的可以拿去用用,可能会存在一些问题,根据自己的业务改改吧 大家也可以多多交流 代码片段:在这里 {"version":"1.1.5","update":[{"title":"修复 [复制代码片段提示] 无法使用的问题","date":"2020-06-15 09:20","imgs":[]}]} 更新日志: 2019-11-25 自定义navigate 也可以调用wx.showNavigationBarLoading 和 wx.hideNavigationBarLoading 2019-11-25 页面滚动条显示在自定义navigate 和 自定义tabbar上面的问题(点击“体验custom Tabbar” [图片] [图片] 其他demo: 云开发之微信支付:代码片段
2020-06-15 - 小程序怎么监听多个input值?
需求表单数据,里面有多个 input 和一个 提交按钮(默认禁用状态) ,input 都输入完毕后 提交按钮可点击 这个需求你们是怎么做的?
2021-11-18 - 样式布局一步一步来,跟着视频来慢慢理解,成就梦想的第一步!
简易入门 内容 选择器"."、颜色和字体、位置、盒模型margin、flex 文件名一定不要用中文 类选择器 class "."开始 11 多个地方被使用 1.2 一个地方使用多个 后面的优先级高 element选择器 page {}、view {} 组合选择器,逗号分隔 ID 选择器 "#"开始 后代选择器 包含元素放在前面,父类里面的子类(空格分隔) 边框属性 [代码]border[代码]四周边框 solid实心 dashed虚线 [代码]border-[代码]可以单独设置一边 字体设置 font-weight 加粗 普通 font-family 字体样式(一般不调) font-size 字体大小 盒模型 · margin外边距(在最外层) · padding内边距(在内容之外) · border边框(padding之外) 做小程序的时候,尽量不用 px, 用"%"来代替px box-sizing content-box border-box 位置偏移 relative相对于自己位置偏移 absolute相对于非static最近的父级元素 fixed一般来说相对于视窗(滚动条,始终在视窗中) 位置 display:flex; (设置在父元素,里面有很多子元素) justify-content 设置主轴的分布 align-items设置侧轴的对齐 [代码]10vh[代码]是把屏幕分成多少份的意思 scroll-y=“true” 实现y轴上的可以滑动 因为scroll无法使用[代码]flex-grow: 1[代码]所以需要在外面再给它包裹一层让底部可以现实 line-hight:1 行距设小 [图片] 耶!!跟着视频敲终于敲出来,大致上是相似了,因为前端知识只是粗略了解了,但是布局真的是个大难题,看着视频敲很简单,但是自己操作的话就很难,例如这个头部这里的设置也是一个麻烦!
2021-11-17 - 【入门】小程序的图片应该放在哪里?不妨试试强大的云存储功能
开发小程序的过程是离不开image组件的,如果图片比较少,我们可以直接把图片存储在本地,加入代码包一起上传,但在图片数量多、体积大的时候,将图片存储在本地可能会超过代码包的限制,显然不是一个好的选择。常用的存储方式是将图片传到服务器上,但并不是每个开发者都有自己的服务器,本文将介绍微信云开发中的云存储功能,可以方便快捷、可视化地管理小程序的文件。 打开微信开发者工具,点击左上角的云开发,打开云开发控制台,点击存储进入云存储界面。 [图片] [图片] 在存储管理界面,我们可以点击上传文件、上传文件夹的方式来上传文件,也可以直接从电脑上拖取文件上传,这里我在test文件夹中上传了一张图片,点击文件就可以看到图片的详细信息,例如ETag,下载地址和File ID等。 [图片] 回到小程序,在.wxml中使用image组件,设置参数src为图片的下载地址和File ID都可以显示图片,往往我们还会设置mode="widthFix"来让图片自适应宽度比例显示,代码如下: <!--index.wxml--> <image src="图片的下载地址 形式为https://..."></image> <image src="图片的File ID 形式为cloud://..." mode="widthFix"></image> 显示效果如下图,第二张图片的比例更接近原图: [图片] 当然,云存储的强大之处可不只是上传图片,你可以配合云函数来实现小程序内的上传、下载和删除文件,还可以根据文件ID换取临时文件网络链接,详细使用方法请参考官方文档https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/storage.html
2021-11-07 - 【笔记】WXSS中定位属性position的使用总结
前言 WXSS (WeiXin Style Sheets)是微信开发的样式语言,用于描述 WXML 的组件样式,它具有CSS 的大部分特性。关于在定位时常用到的属性position,文档中没有对应的描述,所以我自己总结了position的一些基础知识点。 定位 定位的目的是为了更好控制和摆放box,从而实现需要的网页布局。与flex布局的容器、坐标轴等概念不同,定位布局可以轻松任意指定box的摆放位置,定位的属性分为两种,一是边的偏移,二是定位的方式。 边偏移 边偏移有四个属性,分别是top,left,right和bottom,对应于基于顶部,左边,右边和底部的偏移。注意,如果position是默认值,也就是静态定位static时,指定边偏移是无效的行为。例如下面的代码,对于static-view类选择器,我们没有指定position的值,因此position设为默认值static,此时指定属性left是无效的行为: [代码]/* index.wxss */ .static-view{ height: 100px; width: 100px; background-color:red; left:50px; /* position: static; */ } [代码] 显示效果如下,红色正方形仍然贴着屏幕左端: [图片] 定位方式 定位的方式即position的值,常用的有五种,分别是静态定位static(默认值), 相对定位relative, 绝对定位absolute, 固定定位fixed和粘性定位sticky。接下来分别介绍一下各种定位方式的区别。 静态定位 static 静态定位是所有元素的默认定位方式,当你没有为元素指定position的值时,默认值就是static,举个例子,在.wxml中渲染三个不同颜色的view,它们的position都为默认的static: [代码]<!-- index.wxml --> <view class='view-red'></view> <view class='view-blue'></view> <view class='view-green'></view> /* index.wxss */ .view-red{ height: 100px; width: 100px; background-color:red; /* position: static; */ } [代码] 显示效果如下,三个view按照标准流的方式排列: [图片] 注意,在静态定位状态下,无法通过边偏移属性(top、bottom、left或right)来改变元素的位置。 相对定位 relative 相对定位是将元素相对于它的正常位置进行定位的,所谓的正常位置就是position为static时元素在标准文档流中的位置。相对定位的position值为relative,我们修改刚刚红色正方形的position为relative,并设置left为50px: [代码]/* index.wxss */ .view-red{ height: 100px; width: 100px; background-color:red; left: 50px; position: relative; } [代码] 显示效果如下,可以看到红色正方形相对于刚刚的位置向右偏移了50px: [图片] 绝对定位 absolute 绝对定位比较特殊,因为它脱离了标准文档流,以其父容器或父容器中最近的非static(其他四种定位方式)元素的位置为参考。如果没有找到这样的非static元素,就以page作为参考。绝对定位的position值为absolute,我们修改蓝色正方形的position为absolute,并设置left为100px,top为100px;: [代码]/* index.wxss */ .view-blue{ height: 100px; width: 100px; background-color:blue; left:100px; top:100px; position: absolute; } [代码] 显示效果如下,由于没有非static的父容器,view-blue以page为参考位置,left和top指定了它的偏移。还可以看到,绿色正方形在原来的位置向上移动了,原因是蓝色正方形使用了绝对定位,脱离了标准文档流,就为绿色正方形“腾出”了它原来的位置。 [图片] 我们换个例子,让红色正方形作为蓝色正方形的父容器,代码如下: [代码]<!-- index.wxml --> <view class='view-red'> <view class='view-blue'></view> </view> /* index.wxss */ .view-red{ height: 300px; width: 300px; background-color:red; left: 50px; position: relative; } .view-blue{ height: 100px; width: 100px; background-color:blue; left:200px; top:100px; position: absolute; } [代码] 显示效果如下,可以看出此时蓝色正方形以红色正方形的位置作为参考: [图片] 固定定位 fixed 固定定位也脱离了标准文档流,可以把它理解为以page为参考的绝对定位,固定定位的position值为fixed,我们常常会在顶部或底部导航栏中使用固定定位。以自定义tabBar组件为例: [代码].tab-bar { position: fixed; bottom: 0; left: 0; right: 0; height: 48px; background: white; display: flex; padding-bottom: env(safe-area-inset-bottom); } [代码] 显示效果如下,无论如何滚动,tabBar都会固定在屏幕底部。 [图片] 关于自定义tabbar组件,可以查看该代码片段:自定义tabBar组件 粘性定位 sticky 粘性定位的元素依赖于用户的滚动,在相对定位和固定定位之间切换。一般情况下,sticky等同于relative,当页面滚动超出目标区域时,它便切换为fixed,固定在目标位置。目标位置通过指定top, left, right和bottom来设置。修改代码如下: [代码]<!-- index.wxml --> <view style="height:100px"></view> <view class='view-blue'></view> <view class='view-green'></view> <view style="height: 3000px;"></view> /* index.wxss */ .view-blue{ height: 100px; width: 100px; background-color:blue; position: relative; } .view-green{ height: 100px; width: 100px; background-color:green; position: sticky; top:0px; } [代码] 显示如下,此时绿色正方形是相对定位,在标准文档流中: [图片] 下拉滚动条100px,可以看出绿色正方形仍为相对定位: [图片] 继续下拉滚动条,可以发现蓝色正方形消失,但绿色正方形一直处于屏幕顶端,此时已经切换为固定定位: [图片] 覆盖问题 在开发中,我们常常使用子元素绝对定位,父元素相对定位的方法来控制布局,但是仍会遇到不同元素的覆盖现象,可以通过设置属性z-index来解决。z-index的默认值是0,取值越大,定位元素在层叠次序中就越优先;如果取值相同,则以后渲染的优先。 总结 定位布局是各自布局方法中较为简单的一种,它的属性一是边偏移,二是定位方式,两者配合使用才可以构造出美观的布局。
2021-11-10 - 快进来看看简单易懂的分分钟提升小程序性能50%上下的性能优化
场景引入为什么需要用到高性能虚拟列表+节流+分页请求的优化?当有场景需求为需要将大量数据(10000条)呈现在一页上,我们不断下拉访问,页面中有大量的数据列表的时候,用户会不会有不好的体验?会不会出现滚动不流畅而卡顿的情况?会不会因卡顿而出现短暂的白屏现象(数据渲染不成功)? 通过微信开发者工具自带的调试器->Network页面,我们可以观察到当有长列表时如果不使用高性能虚拟列表+节流+分页请求的优化,会出现以下问题: FPS:每秒帧数,图表上的红色块表示长时间帧,很可能会出现卡顿。CPU:CPU消耗占用,实体图越多消耗越高。NET:网络请求效率低,一次性请求10000条的渲染效率远远低于分1000次,每次请求10条数据内存:滑动该列表时明显能看到内存消耗大。总结:如果需要将大量数据(10000条)呈现在一页上,可以通过高性能虚拟列表+节流+按需请求分页数据并追加显示。优化的具体实现可拆分为以下需求(将一个大问题拆分为一个个小问题并逐个去解决): 不把长列表数据一次性全部直接显示在页面上。截取长列表一部分数据用来填充屏幕容器区域。长列表数据不可视部分使用使用空白占位填充。监听滚动事件根据滚动位置动态改变可视列表。监听滚动事件根据滚动位置动态改变空白填充。分页从服务器请求数据,将一次性请求所有数据变为滚动到底部才再次向服务器发送获取数据的请求 更详细的实现方法请阅读我的下一篇文章:https://developers.weixin.qq.com/community/develop/article/doc/000a2618d34908e3610d5978856c13
2021-11-12 - 关于ES6新增的方法总结,包含了一些个人笔记的重点强调
ES6 创建数组: Array.prototype.from(伪数组,函数)//伪数组转换成真数组 Array(length) 设置初始值: Array.of(value) Array.fill(value,start,end)//数组的填充start-end-1都用value填充,可以用于数组值的更改 数组值限制 Array.filter(function)//满足条件的所有值并返回,数组形式。return true时将该数加入新数组,false就过滤掉 Array.map(function)//对数组中的值进行普遍操作,比如全部乘2,就return n*2 查找值 Array.find(function)//满足条件的第一个值就返回,数值形式 Array.findIndex(function)//下标 数组删减增加 Array.splice(index,length,[value])//1.开始下标 2.要删除多少长度 3.替换成后面的值,删除为空 可以改变原数组 数组求和 Array.reduce(function,initValue)//对数组进行合并缩减,最终缩减为一个值 [图片] 数组合并 Array.concat(secondArray) 字符串翻转 string.split("").reverse().join("") class类 原型链 ES5中 类的静态方法(只加到原型上,即Animal.eat=function) 实例对象的方法(要Animal.prototype.eat=function)要加到object的原型对象上,所有的实例才继承 ES6中 加static就是类的静态方法 不加static就是实例对象的方法 类的继承: ES5不管了过于复杂,直接上ES6 Dog继承于Animal class Dog extends Animal {} [图片] 子类中如果没有新构造,例如上图中的this.age=2,那么子类中不需要写constructor(已默认继承) 函数 arguments为传入的参数伪数组 函数形参可以设置默认值:f(x,y=1,z) 如果要用函数默认值,则调用console.log(f(1,undefined,2))//undefined即可,而不能0或空字符串 function sum (…nums)//调用时可以是 sum(1,2,3) data=[1,2,3] function sum(x,y,z)//调用时 sum(…data) 即数组遍历,一边参数散开,一边是数组形式的收 箭头函数 ()=>{} 箭头函数无this,箭头函数内部的this指针为外层 Set 声明时内为可遍历对象, let s=new Set([1,2,3]) s.add()//添加元素 s.has()//是否有某数据 s.size() s.forEach(item => {console.log(item)}) Map let map=new Map([[1,2],[3,4],[“zjc”,“shuaibi”]])//创建map对象同时初始化值 map.set(1,2)//新增 map.delete(1)//删除的是键为1的键值对 map.has()//找的是键值 map.get()//找的是某个键对应的值 map.forEach((value,key)=>{console.log(value,key)})中,是先值再键 对象拷贝 Object.assign(new,old)//直接覆盖,即深拷贝,直接将新的引用到旧的数据上 object和Map存储的都是键值对组合。但是: object的键的类型是 字符串; map的键的类型是 可以是任意类型; 另外注意,object获取键使用Object.keys(返回数组); Map获取键值使用 map变量.keys() (返回迭代器)。 正则表达式 const s=‘aaa_aa_a’ const r1=/a+/g const r2=/a+/y r1.exec(s)//对于对象r1调用该方法,目的是在s中找r1出现的首个下标 /g 全局匹配,从第一位开始 /y 从上一次匹配的位置开始 即第一次执行r2.exec(s)返回0,第二次执行r2.exec(s)返回4 字符串拼接 ``的妙用 es5中用+拼接 es6中用 ``表示字符串,里面的${}内部表示字面量 [图片] ${‘retail’}为传入参数 函数中的s1=string[0]代表传入参数位置的前面的字符串,type为传入的参数, 检查完type==='retail’后,返回传入参数处前面的字符串和函数内部计算后的字符串,即如下 [图片] 字符串换行: [图片] 解构赋值 let arr=[1,2,3] let [zjc,aaa]=arr//以一对应赋值 对于对象(键值对),可以用Object.entries(object)来遍历所有键值对 因此可以用for-of来迭代 for(let [k,v] of Object.entries(user)) {console.log(k,v)} [图片] 如何达到异步机制 Promise对象,then,resolve,reject(这俩为了快速创建promise对象),catch,all,race js是单线程,同步的 先执行完某个作用域中的所有语句,再执行这些语句中引发的另外的事情,下例中先1再2后3 Callback 回调函数 [图片] Promise 返回一个状态(改变同步) 处于pending挂起状态 当第一个文件正确执行后运行onload事件,即执行resolve函数 当第一个文件执行失败运行onerror事件,即执行reject函数 来改变挂起状态 [图片] then 传入两个参数,且返回的是Promise实例 (.then是promise原型的对象和方法) promise.then(onFulfilled,onRejected)//onFullfilled对应上图resolve 必选参数;第二个为可选 如果onFulfilled为非函数,则.then返回空的Promise对象 下例中,第一个return的意思是箭头函数要有一个返回值,将return后面的loadScript得到的promise对象返回给第一个.then,让他能继续作为一个promise继续执行下一个.then [图片] 用Promise对象提供的两个静态方法resolve && reject 实现异步操作 resolve和reject可以快速生成promise实例,而不用new Promise [图片] [图片] Catch 捕获错误 Promise对象的方法,代替reject [图片] 上面的分一个一个接着执行的,为串行 All 对于并行的异步操作 [图片] Race 竞争,异步中的先到先得 Promise.race(p1(),p2()) [图片] Rflect反射机制,未来可能代替object Reflect不用new,直接用 apply 在非反射中(es5中无反射),应用apply就得先指定方法再通过apply改变作用域 反射中可以先apply,再根据执行中的条件去指定要调用哪个方法 用法:Reflect.apply(function,作用域,以数组形式传入的参数) Reflect.apply(Math.floor,null,[4.72])//apply中的null指的是作用域,没指定作用域就默认全局 construct 用于实例化一个类,跟new关键字用法一样 let d=Reflect.construct(Date,[])跟 let d=new Date()一样 construct方法中,第一个参数为什么类,第二个参数为初始化填入的东西,都必填,可以是空数组 修改某对象的原型对象 Reflect.setPrototypeof(old,new)//例如将一个数组改为字符串 例如:Reflect.setPrototypeof(arr,String.prototype) 新增一个寻找某个对象其原型对象的方法 Reflect.getPrototypeof() 验证某个对象上是否有某个属性或方法 Reflect.has(object,属性或方法) 返回某对象的所有键或某数组所有数据的索引值 Reflect.ownKeys(object) Proxy 代理 let d=new Proxy(object,function)//object要代理谁,哪个对象;第二个参数为代理后干什么事,读写 有点像中介[图片] 代理对象禁止赋值(通过set返回false) [图片] 用处:某对象想只能自己修改而用户不能修改,那么将代理对象设置成只读后给用户即可 对代理的写进行限制且 对象结构不被破坏(has限制) [图片] 监控错误 最顶端加,且要捕获而不是冒泡 [图片] 对于错误的处理,可以return false,也可以throw new TypeError(’’) 对新类添加代理,让某个属性只读 [图片] 撤销代理 [图片] 对代理对象进行Proxy.revocable声明,将代理数据和撤销代理方法存到对象d中 接着可以通过d.proxy.price读取数据 d.revoke() 撤销代理 Generator 控制遍历的停止 要点: 控制的函数声明时加星号 function * name(){} 当运行函数时遇到 yield 就会停止,调用.next()让函数继续运行,传递yield后面的结果回去 通过l.next()控制函数执行 [图片] 加星号函数返回给l两个结果,一个是value,遍历的值,另一个是done,是否结束 yield后面加星号,代表后面为可遍历对象 .next(xxx)//next方法可以传参,将参数传给函数体内部yield的返回值,上图中是给val,value空时才能传 .return()//return方法可以控制函数的提前结束 函数外部抛出异常到函数,如何在函数内部捕获该异常? 内部try{}catch{},外部.throw(new Error(’’)) [图片] 可迭代对象 如何将拥有复杂的数据结构的不可迭代对象变为可迭代对象呢?即该对象能用for-of进行遍历 给对象挂载一个Symbol.iterator方法,该方法输入为this,输出为一个对象 该方法的返回值写法为return{next(){return{done:true,value:1}}} 返回值要有next方法,该next方法有两个字段,返回值为done和value, done代表遍历结束没,默认为false没结束,value为遍历开始的值 [图片] [图片] 以上方法为通过控制done是否结束来输出value 以下为通过yield来按节奏来输出 [图片] 可迭代协议:(for of循环) 允许对象定义他的可迭代行为,比如在for of结构中,哪些值可以遍历到。在js中的某些类型是内置好的可迭代对象,比如:字符串、数组、类型数组、Map对象、Get对象等。而Object类型不可迭代。这些内置可迭代对象可以进行迭代的原因是内部实现了@@iterator 方法,即在该对象或该对象的原型链上有Symbol.iterator属性实现了@@iterator 方法。 简单来说就是将不可迭代对象变为可迭代对象,上例手写该协议,用Generator实现,yield控制输出 迭代器协议:(Iterator对象) 定义了产生一系列值的标准方式。一个对象必须实现next()方法,才能成为迭代器。 next() 方法必须返回一个对象,该对象应当有两个属性: done 和 value done(boolean)如果迭代器可以产生序列中的下一个值,则为 false。 value 迭代器返回的任何 JavaScript 值 模块 导出 export {const one=‘name’} 导入 import {name} from ‘xxx文件,可以省略.js拓展名’ 对于默认导出和对导入的模块进行改名 export default 变量名//只能有一个默认导出 在导入时,对于默认导入变量不写在{}里,例如import name2,{name} from ‘src’ 如果想对模块改名,默认变量直接改,其他得加as 例如,原文件默认导出为name,导入时 import name2,{addr as addr2} from ‘src’ 如果导出的是对象,只能导出一个对象, 可以import对象后,进行结构化赋值取出该对象里涵盖的多个对象 默认导出类时,可以不声明类名 如果想一次性导入多个模块,可以用*关键字,例如 import * as Mod from ‘src’ 注意:默认导出的模块需要用Mod.default()//默认去查找 觉得该篇文章有用的请不要忘记忘记点击右下角的大拇指~ 欢迎大家关注我的公众号:Smooth前端成长记录 公众号同步更新CSDN博客内容,想方便阅读博客的C友可以来关注我的公众号以便获得更优良的阅读体验~ [图片]
2021-11-15 - ES6实现简易抽奖模块
博客主页:https://blog.csdn.net/weixin_53893220?spm=1001.2101.3001.5343 本文代码将展示用Generator实现抽奖的可控制化,用yield来控制每次的抽奖结果输出 对抽奖按钮自定义后,每次点击按钮都调用person对象的内置next方法进行数值的输出,从而达到控制抽奖的进行,而不是一次性将所有得奖人物都输出,es6的妙用 js部分代码如下: [代码]function* chouJiang(firstPeople, SecondPeople, thirdPeople) { let first = ['1a', '1b', '1c', '1d'] let second = ['2a', '2b', '2c', '2d', '2d', '2e', '2f'] let third = ['3a', '3b', '3c', '3d', '3e', '3f', '3g', '3h'] let count = 0 let totalSum = 6 let random while (1) { if (count < firstPeople) { random = Math.floor(Math.random() * first.length) yield first[random] count++ first.splice(random, 1) } else if (count < firstPeople + SecondPeople) { random = Math.floor(Math.random() * second.length) yield second[random] count++ second.splice(random, 1) } else if (count < firstPeople + SecondPeople + thirdPeople) { random = Math.floor(Math.random() * third.length) yield third[random] count++ third.splice(random, 1) } else { return false } } } let person = chouJiang(1, 2, 3) // console.log(person.next().value) // console.log(person.next().value) // console.log(person.next().value) // console.log(person.next().value) // console.log(person.next().value) // console.log(person.next().value) // console.log(person.next().value) [代码] 在这里模仿的实际抽奖,first,second,third三个数组为参与对应奖项的待定人选, 给该抽奖函数传入的参数为(1,2,3),即一等奖一名,二等奖两名,三等奖三名 html代码如下: [代码]<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- <script src="异步test.js"></script> --> <script src="抽奖.js"></script> <style> button { width: 100px; height: 100px; font-size: 40px; text-align: center; } </style> </head> <body> <button onclick="console.log(person.next().value)">抽奖</button> <p id="demo"></p> </body> </html> [代码] 觉得该篇文章有用的请不要忘记忘记点击右下角的大拇指~
2021-11-15 - page-container这个组件怎么实现水平垂直居中?
page-container这个组件怎么实现水平垂直居中?
2021-11-15 - 小程序official-account 标签
<official-account></official-account> 这个标签显示之后点击按钮隐藏,然后在点按钮显示, <official-account ></official-account>这个就显示不出来了,有解决的办法吗?? 现在需求是<official-account></official-account>要点击按钮可显示隐藏
2019-03-30 - 搜索不到小程序、公众号
是否是七天内注册或者改名的? 如果是的话,可以再等几天 排名比较低,没有滑到底? 由于小程序、公众号的简介、昵称、关键词等没有设置好导致搜索权重比较低。 是否受到官方的私信?违规被限制搜索? 打开小程序、公众号的后台查看私信,看看近期是否因为违规被限制搜索,如果存在的话,按照官方的指示进行修改。
2021-11-14 - wx.getUserInfo 切换到 wx.getUserProfile
看了一下很久以前的小程序,发现之前用的wx.getUserInfo需要进行修改 官方的文档 https://developers.weixin.qq.com/community/develop/doc/000cacfa20ce88df04cb468bc52801?highLine=getUserInfo%2520%25E5%2588%2587%25E6%258D%25A2%25E5%2588%25B0%2520getUserProfile 因为微信修改了规则 所以原来的wx.getUserinfo不能够使用了 所以使用wx.getUserProfile /** * 判断用户是否登录 */ jugdeUserLogin: function(event) { var that = this wx.getUserProfile({ desc:'登录', success:(res)=>{ that.data.user = res.userInfo; console.log(that.data.user) that.formSubmit(); }, fail:(res)=>{ // debugger console.log(res) } }); // // 查看是否授权 // wx.getSetting({ // success(res) { // if (res.authSetting['scope.userInfo']) { // // 已经授权,可以直接调用 getUserInfo 获取头像昵称 // wx.getUserInfo({ // success: function(res) { // that.data.user = res.userInfo; // console.log(that.data.user) // } // }) // } // } // }) }, 可以看一下我的注释部分是之前的版本的 同时我还删除了 button 中的open-type的属性 变得地方就在跳转而已,其他没有大的变化。
2021-11-10 - 调用云函数获取openid、联表查询、分页数据
为首页获取内容设计了用户集合、表单集合 用户集合:是用户同意授权之后将userInfo信息上传该集合 表单集合是在用户授权之后,通过表单发帖 利用封装好的一个云函数(多个方法)获取openid赋值给userId作为表单合集的字段,准备与用户集合的openid联表查询 封装分页功能到同一云函数,在首页获取你所需要的用户数据 [代码]// 云函数入口文件 const cloud = require("wx-server-sdk"); cloud.init({ env: "你自己的环境名", traceUser: true, }); const db = cloud.database(); const _ = db.command; const $ = db.command.aggregate; //开始封装云函数 exports.main = async (event, context) => { switch (event.action) { case "getid": return getId(); //用户集合与表单集合的联合查询+分页数据 case "reload": return reLoad(event); } // 封装接口 user_openid 不要忘记async与await async function getId() { const wxContext = await cloud.getWXContext(); return { event, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, }; } //联表查询+分页数据 async function reLoad(e){ //集合名称 let dbName = e.dbName; //筛选条件 默认为空 let filter = e.filter ? e.filter : null; //当前页 默认为1 let pageIndex = e.pageIndex ? e.pageIndex : 1; //数据显示条数 默认为20 let pageSize = e.pageSize ? e.pageSize : 20; //获取集合中的总记录 let countResult = await db.collection(dbName).where(filter).count(); //总记录数 let countTotal = countResult; //计算需要多少页 取整数 let totalSize = Math.ceil(countTotal / 20); //将最后的查询结果返回给小程序端 return db .collection(e.dbName) .aggregate() .lookup({ //要匹配userIndex集合的openid字段 from: "userIndex", localField: "userId", foreignField: "_openid", as: "userlist", }) .match(filter) .skip((pageIndex - 1) * pageSize) .limit(pageSize) .end() .then((res) => { return res; }) .catch((err) => { return err; }); } } [代码] 写好云函数记得部署 [图片] 点击授权触发云函数获取openid 赋值给userId [代码]wx.cloud.callFunction({ name:"云函数名", data:{ action:"getid", }, complete: (res) => { console.log("openid: ", res); this.setData({ userId: res.result.openid, }); }, } }) [代码] 截图 [图片] 之后将openid与表单数据一起上传到表单集合,之后通过openid获取两集合的联合查询数据,同时分页 [代码]wx.cloud.callFunction({ name:"云函数名", data:{ action:"reload", dbName:"表单集合名", filter:{限制条件对象}, }, success: (res) => { console.log(res); }, fail: (err) => { console.log(err); }, } }) [代码] 获取的数据截图 [图片]
2021-03-04 - 小程序开发笔记#1 封装一个页面栈工具类:思路分析(一)
为啥想要写一个页面栈工具类? 关于官方API 微信官方文档中提供了有关路由的5个API,对应实现不同的页面切换需求,分别为: wx.switchTab(Object object) wx.navigateTo(Object object) wx.navigateBack(Object object) wx.reLaunch(Object object) wx.redirectTo(Object object) 改进思路(主要还是打代码的习惯) 1)5个API可以看作页面栈的进出栈操作 tabBar之间的跳转 保留当前页面,跳转到应用内的某个页面(但是不能跳到 tabbar 页面)——push(进栈) 关闭当前页面,返回上一页面或多级页面——pop(出栈) 关闭所有页面,打开到应用内的某个页面——清空栈后push一个页面 关闭当前页面,跳转到应用内的某个页面(但是不能跳 tabbar 页面)——先pop后push一个页面 不妨尝试封装一个页面栈工具类,通过更简洁的进出栈操作实现页面切换 2)要实现页面间跳转时的数据传输,一般采用把data放入url中,如: [代码]wx:navigateTo({ url: '../pageTest/pageTest?id=123&name='bao'' }) [代码] 在目标页面pageTest的onload方法中可以这样获取数据: [代码]onLoad: function (res) { this.setData({ id:res.id, name:res.name }) console.log(this.data.id); console.log(this.data.name) }, [代码] 可以看到,对于大量数据的传输时,url会非常长,处理起来比较不方便,我们可以尝试封装一些方法实现从要传输数据对象到url的转换 NavigateUtilAPI push(page页面地址,data需要传递的数据) pop(delta返回层数) switch(page页面地址,data需要传递的数据):进行tabBar间的切换 change(page页面地址,data需要传递的数据):改变当前页面 goto(page页面地址,data需要传递的数据):强制跳转 (……更加细化的接口,如将data嵌入url,当前页面获取等 后记 下一节开始写代码实现!希望能对刚开始学小程序的朋友有所帮助! 还是小白,如果有错误或更好的想法,欢迎各位大佬一同交流、指出哇~
2021-11-13 - 【笔记】横向滑动列表的渲染
前言 今天在学习列表渲染的时候,尝试实现了支持横向滑动的列表,但是遇到了很多问题,做一个小小的总结。 组件scroll-view scroll-view是一种视图容器,指定可滚动视图区域。通过设置属性scroll-y=true并给给scroll-view一个固定高度height,可以实现竖向滚动;通过设置属性scroll-x=true可以实现横向滚动,其他的属性可以参考官方文档。 列表渲染 列表渲染是一种很基础的渲染方法,在组件上使用 wx:for 绑定一个数组,即可使用数组中各项的数据重复渲染该组件。在组件中,使用 wx:for-item 可以指定数组当前元素的变量名,默认为item;使用 wx:for-index 可以指定数组当前下标的变量名,默认为index;使用 wx:key 来指定列表中项目的唯一的标识符,可以提高渲染效率(没有特殊需求的话可以直接用index指定)。 例如,在.js中声明一个含有六个元素的数组list,可以用以下代码循环地渲染list中的所有元素 [代码]<!-- index.wxml 列表渲染 --> <view wx:for="{{list}}" wx:key="{{index}}" class="view-parent"> <view class="view-item">{{item.txt}}</view> </view> [代码] 显示效果如下: [图片] 横向滑动列表 将组件scroll-view和列表渲染结合,就可以实现横向滑动列表了,样例代码如下: [代码]<!-- index.wxml 横向滑动列表 --> <text style="margin-left: 40%;">横向滑动列表</text> <scroll-view scroll-x="true" class="scroll-x-list"> <view wx:for="{{list}}" wx:key="{{index}}" class="view-parent"> <view class="view-item">{{item.txt}}</view> </view> </scroll-view> /* index.wxss */ .scroll-x-list{ height:150px; } .view-item{ width:100px; height:100px; background:#1bf891; margin:10px; } [代码] 显示效果如下: [图片] 可以看到结果和预期差很多,不仅没有实现横向滑动,还没有显示出所有的元素。原因是代码虽然在组件中设置了需要的属性,但是在样式上没有做对应的调整,我们必须在wxss中设置布局才可以达到预期效果。最容易想到的就是我们常用的flex布局,关于flex布局的内容比较多,这里就不展开了,推荐看官方文档学习。在进行下一步修改前,先声明几个必须要知道的小细节: 组件scroll-view是不支持flex布局的,要想在scroll-view中使用flex布局,必须嵌套一个其他的支持flex布局的容器,如view。 scroll-view 中的需要滑动的元素不可以用 float 浮动。 scroll-view 中在需要装载滑动元素的父容器中开启flex布局是没有作用的,应该使用dislay:inline-block来进行元素的横向编排。 第一种方法,由于要实现的是横向滑动列表,那么容器中的元素一定是不允许换行的,刚刚提到,scroll-view是不支持flex布局的,所以开启flex布局并设置flex-wrap=nowrap是无效的行为。我们选择在类scroll-x-list中设置white-space: nowrap来处理元素中的空白,让容器内的换行无效。同时,还应设置装载滑动元素的父容器——view-parent的dislay为inline-block,代码如下: [代码]/* index.wxss */ .scroll-x-list{ height:150px; white-space: nowrap; } .view-parent{ display:inline-block; } [代码] 显示效果如下,已经可以横向滚动列表了。 [图片] 第二种方法,可以在scroll-view中嵌套一个view,在这个view中开启flex布局并设置flex-wrap=nowrap来阻止换行,代码如下: [代码]<!-- index.wxml 另一种横向滑动列表 --> <text style="margin-left: 40%;">横向滑动列表</text> <scroll-view scroll-x="true" class="scroll-x-list"> <view class='flex-view'> <view wx:for="{{list}}" wx:key="{{index}}" class="view-parent"> <view class="view-item">{{item.txt}}</view> </view> </view> </scroll-view> /* index.wxss */ .scroll-x-list{ height:150px; } .flex-view{ display:flex; flex-wrap: nowrap; } .view-parent{ display:inline-block; } [代码] 显示效果与刚刚相同: [图片] 一些改进 在第一种方法中,我们没有使用到flex布局,就很容易遇到一些对齐的问题,假设我们设置数组中第三个元素为空,就会出现下面的情况: [图片] 原因很简单,inline-block的属性中在某个元素没有内容的情况下,它的基线对齐方式是基于这个元素的底边的,解决方式是设置一个垂直的对齐方式: [代码]/* index.wxss */ .view-parent{ display:inline-block; vertical-align: top; } [代码] 显示效果如下: [图片] 同时,你会发现第二种开启flex布局方法的横向列表不会有这种对齐的问题,我们还可以在装载滑动元素的容器中开启flex布局来让内容更加美观: [代码].view-item{ width:100px; height:100px; background:#1bf891; margin-right: 20px; align-items:center; display:flex; justify-content:center; } [代码] 显示效果如下: [图片] 总结 scroll-view是一个十分常见实用的组件,但是使用时也有一些需要注意的问题,比如不支持直接使用flex布局。总体来看,比起设置inline-block的布局,更推荐在scroll-view中嵌套一层view再开启flex布局的方法,可以更灵活的摆放控制滑动元素。
2021-11-15 - 关于微信小游戏可视化开发工具的常见问题20211105
常见问题 为了让大家更快更好的熟悉工具,每周会把大家的问题进行汇总并给出一个解决方案,方便大家参考! 1.如何设定物体向下落的时候不穿透地面呢 下面的物体设置静态刚体 [图片] 2.请问如果不能导入GIF图片,那怎么做到物体的自己走动?这样的效果呢? 换成帧动画,详情可以查看文档:资源管理 [图片] 3.请问如何在游戏结束之后获取用户信息 要点击之后才能获取 [图片] 4.这样子的积木为什么切换不到场景二呢? [图片] 这个积木主要检测的是运动中的精灵,通过积木去修改大小不起作用,改成这样: [图片] 5.发布在社区的游戏可以加入广告吗? 建议申请软著,可以不填
2021-11-05 - 小白怎么制作小程序?
大佬们,小白怎么入门啊
2021-11-07 - 更改小程序其他页面的顶部标题
如何更改小程序其他页面的顶部标题? 作为刚入门微信小程序开发的小白,自己在开发过程中发现,小程序的每个页面顶部都有一个标题,可在[代码]app.json[代码]中进行设置,但是其他页面会默认显示[代码]navigationBarTitleText[代码]中设置的标题。如果需要每个页面有自己的标题,应该怎样做呢? 经过上网查询资料未果后,我就在微信开放社区中提问了。没想到没过多久就收到了几位大佬的评论解答,在此十分感谢他们。 原来在微信开发文档中就有这个问题的答案 [图片] 当我们需要给每个页面设置单独的标题时,就要在当前页面的文件夹下新建一个[代码].json[代码]的配置文件,[代码]navigationBarTitleText:[代码],我们就可以设置自己想要的标题了。 总之,这算是自己开发过程中遇到的一个小问题,记录一下,感谢大佬们的帮助,希望能帮到有需要的人。
2021-11-08