wx小程序笔记(2)

wx小程序笔记

  • 第三章:常用组件
      • 第一节:scroll-view组件
          • view:
          • scroll-view:
          • 设置横向滚动:
          • 设置竖向滚动:
          • scrolltoupper和scrolltolower事件:
          • bindscroll事件:
      • 第二节:swiper组件
          • swiper组件基本用法:
          • swiper常用属性:
      • 第三节:movable-view组件
          • movable-view常用属性:
      • 第四节:icon组件
      • 第五节:text组件
          • rich-text(富文本)
          • progress(进度条)
      • 第六节:input组件
          • type属性:
          • cursor-spacing:
          • confirm-type:
      • 第七节:button(按钮)
      • 自定义组件
          • 一、创建组件:
          • 二、使用组件:
          • 三、给自定义组件添加属性:
          • 三、在组件中添加节点:
          • 组件样式注意事项:
          • 事件:
          • 生命周期:
            • 组件本身的生命周期:
            • 监听组件所在页面的生命周期:
  • 第四章:小程序API
      • 第一节:网络请求API
  • 第五章:ES6语法
      • 第一节:什么是ES6语法
          • 一、一个常见的问题是,ECMAScript 和 JavaScript 到底是什么关系?
          • 二、ES6 与 ECMAScript 2015 的关系:
          • 三、一句话总结:
          • 四、在小程序开发工具中开启ES6:
      • 第二节:定义变量
          • ES6语法:
          • 定义变量的新关键字:
            • let:
            • const:
      • 第三节:函数
          • 默认参数:
          • 箭头函数:
          • Promise风格的调用:
      • 第四节:类
          • 类:
          • 定义静态方法:
      • 第五节:模块
          • 模块:
          • export:
          • import:
  • 第六章:云开发
      • 第一节:什么是云开发
      • 第二节:注册微信小程序
      • 第三节:开通云开发
          • 一、 创建云开发项目:
          • 二、开通云开发服务:
      • 第四节:数据库准备
          • 数据库:
            • 一、兼容性:
            • 二、创建程序:
            • 三、初始化云开发:
          • 创建集合:
      • 第五节:数据库操作
          • 一、初始化:
          • 二、操作数据:
            • 2.1.插入数据(接着上面):
            • 2.2.读取数据:
            • 2.3.删除数据:
            • 2.4.更新数据:
            • 2.5.更新指令:
      • 第六节:command指令
          • 查询指令:
            • command.eq:
            • command.neq:
            • command.lt:
            • command.lte:
            • command.gt:
            • command.gte:
            • command.in:
            • command.nin:
            • command.and:
            • command.or:
          • 更新指令:
            • command.set:
            • command.remove:
            • command.inc:
            • command.mul:
            • command.push:
            • command.pop:
            • command.shift:
            • command.unshift:
      • 第七节:高级查询
          • collection.count:
          • collection.orderBy:
          • collection.limit:
          • collection.skip:
          • collection.field:
          • 正则表达式:
      • 第八节:文件操作
      • 第九节:node环境搭建
          • node环境搭建
          • nvm安装:
          • node安装:
          • npm:
          • 安装包:
          • 本地安装
          • 全局安装
          • 卸载包:
          • 更新包:
          • 搜索包:
          • 使用淘宝镜像:
      • 第十节:云函数
          • 初始化环境:
          • 创建云函数:
          • 上传和部署:
          • 在云函数中操作数据库:
      • 第十一节:检测内容安全
          • 云函数检测内容安全
          • 先获取AppID和AppSecret:
          • 获取access_token:
          • 获取结果:
      • 第十二节:图片鉴黄
      • 第十三节:用户授权
          • 用户授权
          • 过期的授权方式:
          • 新的授权方式:
      • 第十四节:其他授权方式
          • 其他授权方式
          • 在app.json中配置:
          • 授权:
          • 获取数据:

第三章:常用组件

第一节:scroll-view组件

view:

视图容器。相当于是传统网页中的div,可以用来存放任何的其他子元素。相关的属性请参考

scroll-view:

有时候我们的一些视图在手机指定的宽度和高度不够存放。那么可以放在scroll-view中。

设置横向滚动:

scroll-view添加scroll-x="{{true}}"属性。
scroll-view添加white-space:nowrap;样式。
scroll-view中的子元素设置为display:inline-block;
示例代码如下:
index.wxml代码:

<scroll-view class='scroll-x-view' scroll-x="{{true}}">
  <view class='scroll-view-item bg_red'>view>
  <view class='scroll-view-item bg_blue'>view>
  <view class='scroll-view-item bg_green'>view>
  <view class='scroll-view-item bg_yellow'>view>
scroll-view>

index.wxss代码:

.scroll-x-view{
  width: 100%;
  height: 200px;
  background: #43234f;
  white-space: nowrap;
}

.scroll-x-view .scroll-view-item{
  width: 100px;
  height: 100px;
  display:inline-block;
}
.bg_red{
  background: red;
}
.bg_blue{
  background: blue;
}
.bg_green{
  background: green;
}
.bg_yellow{
  background: yellow;
}
设置竖向滚动:

scroll-view添加scroll-y="true"属性。
scroll-view设置高度。
wxml和wxss示例代码如下:

<scroll-view class='scroll-y-view' scroll-y="{{true}}">
  <view class='scroll-view-item bg_red'>view>
  <view class='scroll-view-item bg_blue'>view>
  <view class='scroll-view-item bg_green'>view>
  <view class='scroll-view-item bg_yellow'>view>
scroll-view>
.scroll-y-view{
  width: 100%;
  height: 200px;
  background: gray;
}
.scroll-y-view .scroll-view-item{
  width: 100%;
  height: 100px;
}
.bg_red{
  background: red;
}
.bg_blue{
  background: blue;
}
.bg_green{
  background: green;
}
.bg_yellow{
  background: yellow;
}
scrolltoupper和scrolltolower事件:

鼠标滚动到距离顶部或者左边、鼠标滚动到底部或者右边多少距离的时候会执行这个事件。默认的间隔是50像素。示例代码如下:

<scroll-view class='scroll-x-view' scroll-y bindscrolltoupper="scrollToUpper">
<view style="height:1000px;">
view>
scroll-view>
Page({
  scrollToUpper: function(event){
    console.log(event);
  }
});
bindscroll事件:

只要scroll-view发生了滚动,就会执行这个事件。

<scroll-view class='scroll-x-view' scroll-y bindscrolltoupper="scrollEvent">
<view style="height:1000px;">
view>
scroll-view>
Page({
  scrollEvent: function(event){
    console.log(event);
  }
});

第二节:swiper组件

在app里面,轮播图(banner)是非常常见的,因此小程序专门针对这个出了一个组件就是swiper。

swiper组件基本用法:

swiper就是一个包裹轮播图的容器,里面的子元素必须是swiper-item组件。swiper可以自动的轮播子元素,并且天生就带有指示点,还可以使用手指左右滑动。下面用代码的方式来演示一下:

<swiper class='swiper' style='width:{{width*2}}rpx;height:{{height*2}}rpx;' 
autoplay indicator-dots indicator-color='blue' indicator-active-color='red'>

  <swiper-item>
    <image src='https://static-image.xfz.cn/1539770831_872.jpg'>image>
  swiper-item>
  <swiper-item>
    <image src='https://static-image.xfz.cn/1541147489_121.jpeg'>image>
  swiper-item>
swiper>
.swiper image{
  width: 100%;
  height: 100%;
}
Page({
  data:{},
  onLoad: function (options) {
    var systemInfo = wx.getSystemInfoSync();
    var windowWidth = systemInfo.windowWidth;
    var width = windowWidth;
    var height = width/4;
    // 根据图片的宽高比例设置swiper的宽高
    this.setData({
      width: width,
      height: height
    });
  },
});

效果图如下:
wx小程序笔记(2)_第1张图片

swiper常用属性:
属性名 类型 默认值 说明 最低版本
indicator-dots Boolean false 是否显示面板指示点
indicator-color Color rgba(0, 0, 0, .3) 指示点颜色 1.1.0
indicator-active-color Color #000000 当前选中的指示点颜色 1.1.0
autoplay Boolean false 是否自动切换
current Number 0 当前所在滑块的 index
current-item-id String “” 当前所在滑块的 item-id ,不能与 current 被同时指定 1.9.0
interval Number 5000 自动切换时间间隔
duration Number 500 滑动动画时长
circular Boolean false 是否采用衔接滑动
vertical Boolean false 滑动方向是否为纵向
previous-margin String “0px” 前边距,可用于露出前一项的一小部分,接受 px 和 rpx 值 1.9.0
next-margin String “0px” 后边距,可用于露出后一项的一小部分,接受 px 和 rpx 值 1.9.0
display-multiple-items Number 1 同时显示的滑块数量 1.9.0
skip-hidden-item-layout Boolean false 是否跳过未显示的滑块布局,设为 true 可优化复杂情况下的滑动性能,但会丢失隐藏状态滑块的布局信息 1.9.0
bindchange EventHandle current 改变时会触发 change 事件,event.detail = {current: current, source: source}
bindanimationfinish EventHandle 动画结束时会触发 animationfinish 事件,event.detail 同上 1.9.0

第三节:movable-view组件

正常情况下,一个组件设置了后,如果不通过js或者css动画,那么是很难实现移动的。如果我们有些组件设置完成后想要能够移动。那么我们就可以借助movable-view组件来实现。

movable-view组件,正如他的名字一样,是可以移动的容器,但是这个容器必须要放在movable-area中才能移动。因此实际上是这两个组件配合使用才能实现移动的效果的。看以下示例代码:

<movable-area class="area" scale-area>
  <movable-view class='view' direction="all" inertia out-of-bounds damping="10" friction="0" scale>知了黄勇movable-view>
movable-area>
.area{
  width: 200px;
  height: 200px;
  background: blue;
}

.area .view{
  width: 100px;
  height: 100px;
  background: red;
}
movable-view常用属性:
属性名 类型 默认值 说明 最低版本
direction String none movable-view的移动方向,属性值有all、vertical、horizontal、none
inertia Boolean false movable-view是否带有惯性
out-of-bounds Boolean false 超过可移动区域后,movable-view是否还可以移动
x Number/String 定义x轴方向的偏移,如果x的值不在可移动范围内,会自动移动到可移动范围;改变x的值会触发动画
y Number/String 定义y轴方向的偏移,如果y的值不在可移动范围内,会自动移动到可移动范围;改变y的值会触发动画
damping Number 20 阻尼系数,用于控制x或y改变时的动画和过界回弹的动画,值越大移动越快
friction Number 2 摩擦系数,用于控制惯性滑动的动画,值越大摩擦力越大,滑动越快停止;必须大于0,否则会被设置成默认值
disabled Boolean false 是否禁用 1.9.90
scale Boolean false 是否支持双指缩放,默认缩放手势生效区域是在movable-view内 1.9.90
scale-min Number 0.5 定义缩放倍数最小值 1.9.90
scale-max Number 10 定义缩放倍数最大值 1.9.90
scale-value Number 1 定义缩放倍数,取值范围为 0.5 - 10 1.9.90
animation Boolean true 是否使用动画 2.1.0
bindchange EventHandle 拖动过程中触发的事件,event.detail = {x: x, y: y, source: source},其中source表示产生移动的原因,值可为touch(拖动)、touch-out-of-bounds(超出移动范围)、out-of-bounds(超出移动范围后的回弹)、friction(惯性)和空字符串(setData) 1.9.90
bindscale EventHandle 缩放过程中触发的事件,event.detail = {x: x, y: y, scale: scale},其中x和y字段在2.1.0之后开始支持返回 1.9.90

第四节:icon组件

更多详情请查看小程序官方文档

第五节:text组件

官方文档

除了以上官方文档中描述的,还需要注意:

  1. text组件是行内元素,在布局的时候不会占据一整行。
  2. 给text组件设置宽高是没有效果的,他的宽高是根据里面的文字来的。
rich-text(富文本)

官网

progress(进度条)

官网

第六节:input组件

主要的资料请参考

这里补充几点:

type属性:
  1. number类型:
    wx小程序笔记(2)_第2张图片
  2. text类型:
    wx小程序笔记(2)_第3张图片
  3. idcard类型:
    wx小程序笔记(2)_第4张图片
  4. digit类型:
    wx小程序笔记(2)_第5张图片
cursor-spacing:

在输入框被键盘挡住的时候,指定光标与键盘的距离,单位px(2.4.0起支持rpx)。取 input 距离底部的距离和 cursor-spacing 指定的距离的最小值作为光标与键盘的距离。如果没有指定这个值,并且输入框被挡到了,那么距离键盘的距离为0。

confirm-type:
  1. search:
    wx小程序笔记(2)_第6张图片
  2. done:
    wx小程序笔记(2)_第7张图片
  3. send
    wx小程序笔记(2)_第8张图片
  4. next:
    wx小程序笔记(2)_第9张图片
  5. go:
    wx小程序笔记(2)_第10张图片

第七节:button(按钮)

官网

自定义组件

一、创建组件:
  1. 自定义一个components文件夹,用来存放所有自定义的组件。
  2. 再针对每一个组件创建一个文件夹,用来存放这个组件相关的文件。比如mybox这个组件,那么可以创建一个mybox的一个文件夹。
  3. 在指定组件的文件夹中右键->新建Component创建组件。这样创建的目的是在json文件中添加"component": true,将其申明为一个组件。
  4. 在wxml文件中做好组件的节点布局。比如以下代码:
<view class="outter">
 <view class="inner">自定义组件view>
view>
.outter{
	width:200px;
	height:200px;
	background:burlywood;
}
.inner{
	width:100px;
	height:200px;
	background:gray;
}
二、使用组件:
  1. 在需要使用自定义组件的页面的json文件中注册组件。添加类似如下代码:
 {
   "usingComponents": {
     "mybox": "/components/mybox/mybox"
   }
 }
  1. 然后在wxml模板文件中使用组件:
<mybox>mybox>
三、给自定义组件添加属性:

在组件的js文件中,在properties中添加属性,添加属性的时候,需要指定两个值,一个是type,代表的是这个属性的类型,一个是value,代表的是这个属性的默认值。示例代码如下:

Component({
 properties: {
   showInner: {
     type: Boolean,
     value: false
   }
 }
})
  1. 然后在wxml模板中就可以使用了。示例代码如下:
<view class="outter">
 <view wx:if="{{showInner}}" class="inner">自定义组件view>
view>
  1. 在使用组件的时候,可以直接在组件上给这个属性设置值:
<mybox showInner="true">mybox>
  1. 还有另外一种使用data的形式,data中的数据可以渲染到组件的代码中,但是使用data不能作为属性来使用。
三、在组件中添加节点:

在使用小程序内置的组件的时候,比如view,我们还可以在view中添加其他的组件。这个功能可以通过slot节点来实现。示例代码如下:

<view class="outter">
  <view wx:if="" class="inner">知了课堂view>
  <slot>slot>
view>

以后在使用这个组件的时候,还可以添加自己的节点。示例代码如下:

<mybox showInner="true">
  <view>这是index中添加的view>
mybox>

以上是添加一个slot,如果想要添加多个slot,那么需要在js文件中添加一个multipleSlots属性,示例代码如下:

Component({
  options: {
    multipleSlots: true
  },
  ...

然后在wxml文件中,需要给每一个slot都指定name。示例代码如下:

<view class="outter">
<slot name="before">slot>
  <view wx:if="" class="inner">自定义组件添加slotview>
  <slot name="after">slot>
view>

最后在使用这个组件的时候,也需要指定放在那个slot中。示例代码如下:

<mybox showInner="true">
  <view slot="before">这是before的组件view>
  <view slot="after">这是after的组件view>
mybox>
组件样式注意事项:

组件对应 wxss 文件的样式,只对组件wxml内的节点生效。编写组件样式时,需要注意以下几点:

  1. 组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器。
  2. 组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用。
  3. 子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况。
    继承样式,如 font 、 color ,会从组件外继承到组件内。
  4. 除继承样式外, app.wxss 中的样式、组件所在页面的的样式对自定义组件无效。
#a { } /* 在组件中不能使用 */
[a] { } /* 在组件中不能使用 */
button { } /* 在组件中不能使用 */
.a > .b { } /* 除非 .a 是 view 组件节点,否则不一定会生效 */
事件:
  1. 组件可以直接再外面绑定事件。示例代码如下:
// my-component组件代码
<view>
 组件内的代码
view>

然后在使用的时候,直接在上面绑定就可以了。

<my-component bindtap="tapEvent">my-component>
  1. 自定义组件事件。直接在组件内绑定事件。并且如果我们想在组件内捕获到事件后,要通知到父组件,那么可以通过triggerEvent方法来触发自定义的事件。示例代码如下:
// my-component组件代码
<view class="outter">
 <view class="inner" bindtap="onInnerTapEvent">view>
view>

然后在组件的js文件中,使用以下代码进行捕获和传递给父组件。示例代码如下:

Component({
 method: {
   onInnerTapEvent: function(event){
     console.log("组件内监听到了innerTapEvent事件");
     var detail = {} // detail对象,提供给事件监听函数
     var option = {} // 触发事件的选项
     this.triggerEvent("customevent",detail,option);
   }
 }
})

然后在使用组件的地方,需要给自定义事件绑定监听方法。示例代码如下:

<my-component bindcustomevent="onCustomEventEvent">
my-component>

其中的detail是在触发innerEvent事件的时候,传递给外面接收这个事件的对象一些额外的信息,option是一些选项。这些选项可以如下:

选项名 类型 是否必填 默认值 描述
bubbles Boolean false 事件是否冒泡
composed Boolean false 事件是否可以穿越组件边界,为false时,事件将只能在引用组件的节点树上触发,不进入其他任何组件内部
capturePhase Boolean false 事件是否拥有捕获阶段
生命周期:
组件本身的生命周期:

组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发。

其中,最重要的生命周期是created/attached/detached,包含一个组件实例生命流程的最主要时间点。(注意:在2.2.3基础库之前,生命周期函数写在Component中就可以,在2.2.3后应该写在lifetimes中。)

  1. 组件实例刚刚被创建好时,created生命周期被触发。此时,组件数据this.data就是在Component构造器中定义的数据data。此时还不能调用setData。通常情况下,这个生命周期只应该用于给组件this添加一些自定义属性字段。
  2. 在组件完全初始化完毕、进入页面节点树后,attached生命周期被触发。此时,this.data已被初始化为组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。
  3. 在组件离开页面节点树后,detached生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则 detached会被触发。
监听组件所在页面的生命周期:

还有一些特殊的生命周期,它们并非与组件有很强的关联,但有时组件需要获知,以便组件内部处理。这样的生命周期称为“组件所在页面的生命周期”,在 pageLifetimes 定义段中定义。其中可用的生命周期包括:

生命周期 参数 描述 最低版本
show 组件所在的页面被展示时执行 2.2.3
hide 组件所在的页面被隐藏时执行 2.2.3
resize Object Size 组件所在的页面尺寸变化时执行

第四章:小程序API

第一节:网络请求API

小程序中的数据,并不是写死的。而是从服务器动态加载的。这时候就需要借助网络请求的api来实现。api全称application programming interface,是小程序提供给开发者的接口。api的调用都是在js文件中完成的。网络请求的api相关的介绍请参考

聚合数据网址

第五章:ES6语法

第一节:什么是ES6语法

一、一个常见的问题是,ECMAScript 和 JavaScript 到底是什么关系?

要讲清楚这个问题,需要回顾历史。1996 年 11 月,JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给标准化组织 ECMA,希望这种语言能够成为国际标准。次年,ECMA 发布 262 号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为 ECMAScript,这个版本就是 1.0 版。

该标准从一开始就是针对 JavaScript 语言制定的,但是之所以不叫 JavaScript,有两个原因。一是商标,Java 是 Sun 公司的商标,根据授权协议,只有 Netscape 公司可以合法地使用 JavaScript 这个名字,且 JavaScript 本身也已经被 Netscape 公司注册为商标。二是想体现这门语言的制定者是 ECMA,不是 Netscape,这样有利于保证这门语言的开放性和中立性。

因此,ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 Jscript 和 ActionScript)。日常场合,这两个词是可以互换的。

二、ES6 与 ECMAScript 2015 的关系:

ECMAScript 2015(简称 ES2015)这个词,也是经常可以看到的。它与 ES6 是什么关系呢?

2011 年,ECMAScript 5.1 版发布后,就开始制定 6.0 版了。因此,ES6 这个词的原意,就是指 JavaScript 语言的下一个版本。

但是,因为这个版本引入的语法功能太多,而且制定过程当中,还有很多组织和个人不断提交新功能。事情很快就变得清楚了,不可能在一个版本里面包括所有将要引入的功能。常规的做法是先发布 6.0 版,过一段时间再发 6.1 版,然后是 6.2 版、6.3 版等等。

但是,标准的制定者不想这样做。他们想让标准的升级成为常规流程:任何人在任何时候,都可以向标准委员会提交新语法的提案,然后标准委员会每个月开一次会,评估这些提案是否可以接受,需要哪些改进。如果经过多次会议以后,一个提案足够成熟了,就可以正式进入标准了。这就是说,标准的版本升级成为了一个不断滚动的流程,每个月都会有变动。

标准委员会最终决定,标准在每年的 6 月份正式发布一次,作为当年的正式版本。接下来的时间,就在这个版本的基础上做改动,直到下一年的 6 月份,草案就自然变成了新一年的版本。这样一来,就不需要以前的版本号了,只要用年份标记就可以了。

ES6 的第一个版本,就这样在 2015 年 6 月发布了,正式名称就是《ECMAScript 2015 标准》(简称 ES2015)。2016 年 6 月,小幅修订的《ECMAScript 2016 标准》(简称 ES2016)如期发布,这个版本可以看作是 ES6.1 版,因为两者的差异非常小(只新增了数组实例的includes方法和指数运算符),基本上是同一个标准。根据计划,2017 年 6 月发布 ES2017 标准。

因此,ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等,而 ES2015 则是正式名称,特指该年发布的正式版本的语言标准。本书中提到 ES6 的地方,一般是指 ES2015 标准,但有时也是泛指“下一代 JavaScript 语言”。

以上内容引用自《ECMAScript 6 入门》

三、一句话总结:

ES6ECMAScript 6的简写,ECMAScriptJavaScript的标准,ECMAScript 6泛指“下一代JavaScript语言”,具体每年发布的都有自己的专属名称,比如2015年发布的则为ESMAScript 2015.目前说的ES6语法,一般值得都是ESMAScript 2015版。

四、在小程序开发工具中开启ES6:

在微信开发者工具中->详情->ES6转ES5,勾选上就可以了!

第二节:定义变量

ES6语法:

因为本课程不是专业的前端课程,只是为了微信小程序的学习做一些铺垫,所以只介绍到一些常用的语法。

定义变量的新关键字:
let:

letvar一样,也是用来定义变量,但是他比var更加的安全,体现在以下两点:

  1. 不会出现变量提升的情况。
 console.log(a);
 var a = 10;

按道理变量a是在打印的后面定义的,但是以上的代码并不会出错,而是会打印undefined,因为var会把变量a提升到代码最开始的地方进行定义。但是如果使用let就不会出现这种问题了。

 console.log(b);
 let b = 10;

此时再去打印的时候,就直接会抛出一个错误ReferenceError: b is not defined.,这才是正确的方式。
注意:小程序中不能真正解析ES6语法,他只是借助了第三方工具将ES6语法转成ES5语法运行的,在底层也是用var来代替let的,所以依然会发生变量提升。

  1. 只在当前代码块内有效。
 for(var i=0;i<=3;i++){
     console.log(i);
 }
 console.log(i);

按道理来说ifor循环结束后,应该就不能够再使用了,但是我们下面再打印i的时候,会发现打印的结果是3而不是抛出异常,这在一些情况下也会产生莫名其妙的错误。但是let就不会出现这种情况了。示例代码如下:

 for(let i=0; i<=3; i++){
     console.log(i);
 }
 console.log(i);

此时再打印i的时候,就会抛出错误ReferenceError: b is not defined.

const:

const是用来定义常量的,常量是一旦定义好了以后,就不能够再修改了。比如以下代码:

const PI = 3.14;
PI = 3 // 会抛出异常

const只是用来限制指向的内存地址不能改变,但是如果这个内存地址上的数据改变了,是可以的。或者说得直白一点,就是指向的如果是一个可变的容器,容器中的数据改变了,那么是允许的。比如以下代码:

const mylist = [1,2,3];
mylist.push(4);
console.log(mylist);

以上代码后面会打印一个[1,2,3,4]的数组。

第三节:函数

默认参数:

在ES 2015之前,函数是不能指定默认参数的,在ES 2015后,就可以使用默认参数了。比如以下代码:

function fetch(url,method="get"){
    // 发送网络请求案例
    console.log(url);
    console.log(method);
}

那么以后我们在使用fetch函数的时候,可以不传method参数,他会默认使用get:

fetch("http://www.baidu.com/"); //method == get
fetch("http://www.baidu.com/","post") // method == post

定义默认参数的时候,默认参数必须要在非默认参数的后面。

如果有多个默认值,我们只想提供其中的一个默认值,那么这时候需要与解构赋值默认值结合使用,示例代码如下:

function person(name,age=18,gender='男'){
    console.log(name,age,gender);
}

比如我只想提供gender这个默认参数,age这个参数不提供,那么必须与解构赋值默认值结合使用实现:

function person(name,{age=18,gender='女'}={}){
    console.log(name,age,gender);
}
person("知了",{gender:"男"});
箭头函数:

有时候,函数作为一个参数变量传进去的时候,为了简化他的写法,我们可以使用箭头函数来实现。比如以下:

wx.request({
    url: "http://www.baidu.com/",
    success: function(res){
        // 做一些事情
    }
});

以上代码可以使用箭头函数进行简化:

wx.request({
    url: 'http://www.baidu.com/',
    success: res => {
        //做一些事情
    }
});

可以看到使用箭头函数更加的简洁。
箭头函数的语法是:

(参数1,参数2) => {代码块}

如果只有一行代码,那么可以不用花括号:
(a,b) => a+b // 返回a+b的结果 

// 如果只有一个参数,可以不使用圆括号
a => a+1
Promise风格的调用:

在云开发中,提供的API有大量的Promise方式调用。在这里就简单的讲解一下Promise的实现原理。看以下代码:

const p = new Promise(function(resolve,reject){
    // 如果执行以下代码,那么会执行下面的then函数
    setTimeout(() => {
        resolve("success");
    },1000);
    // 如果执行以下代码,那么会执行下面的catch函数
    setTimeout(() => {
        reject("fail")
    },1000);
    // 如果以上两个代码都执行,那么只会调用下面的then方法,因为resolve的调用在前面。
});

p.then((res) => {
  console.log(res);
}).catch((error) => {
  console.log(error);
});

以后在云开发中,如果出现then和catch,就知道分别对应的是成功的回调以及失败的回调。

第四节:类

类:

ES5中,如果想要实现一个类,那么需要通过以下代码来实现:

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);

这种写法虽然可以实现,但是不够清晰,让有其他编程语言的小伙伴看了后会有一脸问号。那么ES6就提供了一个新的语法class来实现。示例代码如下:

class Person{
  // 构造函数
  constructor(name,age){
    this.name = name;
    this.age = age;
  }

  sayHello(){
    console.log("hello world");
  }
}

let p = new Person("zhiliao",18);
p.sayHello();

以上便是定义一个Person类的非常简单的方式。

定义静态方法:

在定义方法的时候,可以使用static关键字定义静态方法,静态方法是只属于类的,不属于对象的。示例代码如下:

class Utils{
  constructor(){}
  static timeFormat(time){
    // 时间格式化的代码
  }
}

// 直接调用
Utils.timeFormat("2019/1/1")

以上定义了一个timeFormat的方法,并且在这个方法前面加了一个static关键字,所以他就是一个静态方法了,那么以后在使用这个方法的时候直接通过类名就可以调用了。

第五节:模块

模块:

在传统的JS中,是没有办法在多个js文件中互相导入的,这对于大型项目来说很不方便。因此ES6提供了一个模块的功能。要学会使用模块,只要掌握两个关键字export以及import即可。

export:

默认在一个js文件中写好的代码或者变量,是不能够给其他的文件使用的,如果想要被外部使用,那么需要使用export关键字。示例代码如下:

// utils.js
var name = "zhiliao";
function dateFormat(date){
    // 格式化代码
}
class Person{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
}
export {name,dateFormat,Person}
import:

以上文件进行export了,那么以后其他文件想要使用的,则需要从这个文件中把需要的进行import。示例代码如下:

// from 后面是一个相对路径
import {name,dateFormat,Person} from "utils.js";

第六章:云开发

第一节:什么是云开发

按照正常的流程来说,如果我们想要是想一个能进行网络数据通信的微信小程序。比如:
wx小程序笔记(2)_第11张图片
那么我们不仅需要开发微信小程序,还需要开发一个服务器端程序来保存数据、保存文件、逻辑处理等。并且服务器端还需要专业的运维人员来运维,以防遭受攻击,因此需要的人力和资金成本非常大。而云开发技术就是专门为我们解决服务器端需求的,使用云开发,我们不用关心服务器端运维,数据库的管理,文件的管理等。只需要调用云开发给我们提供的API即可进行服务器端的操作,因此大大的提高了小程序开发的效率。

目前提供三大基础能力支持:

  • 云函数:在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码
  • 数据库:一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库
  • 存储:在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理

第二节:注册微信小程序

注册微信小程序
在微信官网,点击立即注册。示例图如下:
wx小程序笔记(2)_第12张图片
然后选择小程序:
wx小程序笔记(2)_第13张图片
接下来就是填写相关的信息,比如邮箱,密码等:
wx小程序笔记(2)_第14张图片
然后再根据自己的情况,选择到底是申请个人的还是企业的:
wx小程序笔记(2)_第15张图片

第三节:开通云开发

一、 创建云开发项目:

想使用云开发服务,在创建项目的时候就需要选择云开发的模板,并且因为云开发不能使用测试ID,因此在创建项目之前,要先在微信的后台创建好小程序,然后在创建项目的时候填入APPID。

  1. 打开小程序开发工具,创建新的项目,然后模板的地方选择云开发模板:
    wx小程序笔记(2)_第16张图片
    然后再来到小程序的后台->开发->开发设置中,找到AppID,拷贝到开发工具中。示例图如下:
    wx小程序笔记(2)_第17张图片
二、开通云开发服务:

创建完项目后,还需要在项目中开通云开发服务。跟着以下步骤就可以开通云开发服务了。

  1. 点击左上角的云开发按钮:
    wx小程序笔记(2)_第18张图片

  2. 然后来到一个新的界面,接下来再点击开通按钮:
    wx小程序笔记(2)_第19张图片
    wx小程序笔记(2)_第20张图片

  3. 设置环境变量名称:
    wx小程序笔记(2)_第21张图片
    并且默认是可以开通两个环境,一个用于开发,一个用户生产环境。这里我们只开通开发环境就可以了。

  4. 进入云开发控制台:
    wx小程序笔记(2)_第22张图片

第四节:数据库准备

数据库:
一、兼容性:

云开发能力从基础库2.2.3开始支持,现在2.2.3或以上的基础库没有完全覆盖所有用户(目前约90%),如需使上传的代码能够覆盖全量用户,请做以下特殊处理:
app.json / game.json中增加字段"cloud": true
指定后云能力可以在所有基础库中使用,并且如果云能力有更新,并不会随着基础库升级而自动升级,需在后续版本发布后重新上传。如2.2.4发布后,需重新上传才能将云能力更新至2.2.4版本的云能力。

二、创建程序:

在创建完云开发的项目后,默认会生成一个miniprogram项目,这个项目是一些演示性的代码,不符合我们的需求。因此我们重新创建一个新的项目,项目名字可以随便取,比如叫做databasedemo,然后在项目中需要创建好项目所需要的文件,比如app.jsonapp.wxss以及pages文件夹等。创建完项目后,还需要在project.config.json文件中配置"miniprogramRoot":"databasedemo/"

三、初始化云开发:

如果我们想要使用小程序的云开发功能,必须在小程序初始化的时候就调用wx.cloud.init方法来进行初始化,这个方法可以接受两个参数,两个参数的作用如下:

字段 数据类型 必填 默认值 说明
env string \ object default 默认环境配置,传入字符串形式的环境 ID 可以指定所有服务的默认环境,传入对象可以分别指定各个服务的默认环境
traceUser boolean false 是否在将用户访问记录到用户管理中,在控制台中可见

app.js文件中的App.onLaunch方法中调用。示例代码如下:

App({
  onLaunch: function () {
    wx.cloud.init({
        env: "环境ID",
        traceUser: true,
    })
  }
})
创建集合:

在云开发的数据库中,使用的是NoSQL类型的数据库。关系型数据库中的表,对应的是NoSQL中的一个集合。所以在所数据操作之前,应该先创建一个集合。创建完集合后,也不需要跟关系型数据库一样,先定义好这个集合中的字段,而是直接插入数据,并且插入数据的时候,每条数据的字段无需保持一致!

第五节:数据库操作

一、初始化:

在做数据的操作(增删改查)之前,先要获取数据库的对象,可以通过wx.cloud.database函数来获取到,这个函数默认会使用wx.cloud.init方法中提供的环境下的数据库,如果你想要使用其他环境的数据库,可以给wx.cloud.database方法传递一个env参数,比如:wx.cloud.database({“env”:“数据库环境ID”})。

二、操作数据:

在获取到了数据库的对象之后,比如db = wx.cloud.database(),然后就可以进行一些操作了。
操作数据的时候首先要通过db.collection来获取集合对象,比如const article = db.collection(“article”),然后就可以通过article来进行操作了。

2.1.插入数据(接着上面):

在获取到集合的对象后,我们可以调用他的add方法来插入数据。示例代码如下:

const db = wx.cloud.database();
db.collection("article").add({
    data: {
        title: "learn cloud database",
        pub_date: new Date("2019-1-1"),
        author: "知了",
        content: "very good!"
    }
}).then(res => {
    console.log(res);
});
2.2.读取数据:

获取所有数据(考虑到性能,小程序一次性最多只能获取20条数据):

 db.collection("article").get().then(res => {
     console.log(res);
 });

如果你知道某条数据的id,可以根据id获取某条数据:通过id获取数据需要通过doc函数来实现:

 db.collection("article").doc("article id").get().then(res => {
     console.log(res)
 });

根据条件获取数据:根据条件获取数据,可以通过where函数来实现。示例代码如下:

 db.collection("article").where({
     title: "知了"
 }).get().then(res => {
     console.log(res);
 });
2.3.删除数据:

删除一条数据:输出一条数据,需要知道这条数据的id。示例代码如下:

 db.collection("article").doc("article id").remove().then(res => {
     console.log(res);
 });

删除多条数据(只能在服务端实现,需要用到云函数):

 db.collection("article").where({
     title: "知了"
 }).remove().then(res => {
     console.log(res);
 });
2.4.更新数据:

局部数据:局部更新是一次性只更新一条数据中的某几个字段的值,用的是update方法。示例代码如下:

 db.collection("article").doc("article id").update({
     data: {
         title: "知了课堂"
     }
 }).then(res => {
     console.log(res);
 });

整体更新:整体更新是一次性把所有数据都更新,用的是set方法。示例代码如下:

 db.collection("article").doc("article id").set({
     data: {
         title: "知了课堂",
         author: "abc",
         content: "1111",
         author: "ddd"
     }
 });

一次更新多个数据:需要在服务器端,使用云函数来实现。

2.5.更新指令:

更新的方式有很多种,比如给数组添加元素,删除元素等。这些方法可以通过db.command来获取到,以下进行讲解:

  1. set:设置字段为指定值。
  2. remove:删除字段。
  3. inc:自增字段值。
  4. mul:自乘字段值。
  5. push:如字段值为数组,往数组尾部增加指定值。
  6. pop:如字段值为数组,从数组尾部删除一个元素。
  7. shift: 如字段值为数组,从数组头部删除一个元素。
  8. unshift:如字段值为数组,往数组头部增加指定值。

第六节:command指令

查询指令:

在做查询的时候,大部分情况都需要做一些条件查询。在云开发提供的API中,我们可以通过db.command来实现。以下将讲解这些指令的操作:

command.eq:

查询筛选条件,表示字段等于某个值。eq指令接受一个字面量 (literal),可以是number,boolean,string, object,array, Date

比如想要获取作者是北京日报的所有文章:

// 第一种方式,直接通过指定的数据查询:
db.collection("article").where({
    author: "北京日报"
});

// 第二种方式,通过eq指令查询:
const _ = db.command;
db.collection("article").where({
    author: _.eq("北京日报")
});

command.eq与指定数据还是有区别的,比如以下两个作用是不一样的:

// 这种写法表示匹配 stat.publishYear == 2018 且 stat.language == 'zh-CN'
db.collection('articles').where({
  author: {
    name: "知了课堂",
    age: 18
  }
})
// 这种写法表示 stat 对象等于 { publishYear: 2018, language: 'zh-CN' }
const _ = db.command
db.collection('articles').where({
  stat: _.eq({
    name: "知了课堂",
    age: 18
  })
})
command.neq:

表示字段不等于某个值,和db.command.eq相反。

command.lt:

表示小于某个值。比如查找小于2019/1/1 00:00:00发布的文章:

const _ = db.command;
db.collection("article").where({
  pub_date: _.lt(new Date("2019/1/1 00:00:00"))
});
command.lte:

表示小于或者等于某个值。与command.lt类似。

command.gt:

表示大于某个值。与command.lt类似。

command.gte:

表示大于或者等于某个值。与command.lte类似。

command.in:

查询筛选条件,表示字段的值需在给定的数组内。比如查找北京日报和今日头条两个作者发表的文章:

const _ = db.command;
db.collection("article").where({
  author: _.in(['北京日报','今日头条'])
});
command.nin:

查询筛选条件,表示字段的值需不在给定的数组内。与command.int类似。

command.and:

查询指令,用于表示逻辑 “与” 的关系,表示需同时满足多个查询筛选条件。比如获取发表在2019/1/1 00:00:002019/1/1 23:59:59之间的所有文章:

const _ = db.command;
// 普通调用:
db.collection("article").where({
  pub_date: _.and(_.gte(new Date("2019/1/1 00:00:00")),_.lte(new Date("2019/1/1 23:59:59")))
});
// 链式调用:
db.collection("article").where({
  pub_date: _.gte(new Date("2019/1/1 00:00:00")).and(_.lte(new Date("2019/1/1 23:59:59")))
});
command.or:

查询指令,用于表示逻辑 “或” 的关系,表示需同时满足多个查询筛选条件。或指令有两种用法,一是可以进行字段值的 “或” 操作,二是也可以进行跨字段的 “或” 操作。

一个字段的或操作(比如获取时间在2019/1/1 00:00:00前或者2019/1/1 23:59:59后发表的文章):

const _ = db.command;
db.collection("article").where({
 pub_date: _.or(_.lt("2019/1/1 00:00:00"),_gt(new Date("2019/1/1 23:59:59")))
});

跨字段或操作(比如想要获取时间在2019/1/1前,或者是标题中包含知了课堂的文章):

 const _ = db.command;
 db.collection("article").where(
   _.or([{
     pub_date: _.lt(new Date("2019/1/1 00:00:00"))
   },{
     title: /知了课堂/
   }])
 );
更新指令:
command.set:

更新指令。用于设定字段等于指定值。比如以下是一个文章的数据:

{
  "title": "abc",
  "content": "111",
  "author": {
    "name": "知了课堂",
    "age": 18
  }
}

如果我想将这个文章中的author变成{"name":"知了课堂"},那么通过传统的方式是无法实现的:

db.collection("article").doc("id").update({
  data: {
    author: {
      "name": "知了课堂"
    }
  }
})

上面这种方式,只是将author.name设置为知了课堂,并没有将author的值设置为{name:"知了课堂"},也就是说,age:18这个值依然在author中存在。这时候就需要通过set来实现了。示例代码如下:

const _ = db.command;
db.collection("article").doc("id").update({
  data: {
    author: _.set({
      "name": "知了课堂"
    })
  }
})
command.remove:

更新指令。用于表示删除某个字段。比如我们想将author这个字段删除,那么就可以调用这个方法。示例代码如下:

const _ = db.command;
db.collection("article").doc("id").update({
  data: {
    author: _.remove()
  }
})
command.inc:

更新指令。用于指示字段自增某个值,这是个原子操作,使用这个操作指令而不是先读数据、再加、再写回的好处是:

原子性:多个用户同时写,对数据库来说都是将字段加一,不会有后来者覆写前者的情况。
减少一次网络请求:不需先读再写。
比如article这个集合中的一条数据有一个read_count字段,想给这个字段加1,那么可以使用以下方式实现:

const _ = db.command
db.collection('article').doc('id').update({
  data: {
    read_count: _.inc(1)
  }
})
command.mul:

自乘指令,跟command.inc一样。

command.push:

更新指令,对一个值为数组的字段,往数组尾部添加一个或多个值。或字段原为空,则创建该字段并设数组为传入值。
比如要给article集合中的某条数据添加标签,那么可以使用以下方式来实现:

const _ = db.command
db.collection('article').doc('id').update({
  data: {
    tags: _.push(['新闻'])
  }
})
command.pop:

更新指令,对一个值为数组的字段,将数组尾部元素删除。

command.shift:

更新指令,对一个值为数组的字段,将数组头部元素删除。

command.unshift:

更新指令,对一个值为数组的字段,往数组头部添加一个或多个值。或字段原为空,则创建该字段并设数组为传入值。

第七节:高级查询

collection.count:

统计集合记录数或统计查询语句对应的结果记录数,注意这与集合权限设置有关,一个用户仅能统计其有读权限的记录数。比如查找所有由“北京日报”发布的文章的个数:

db.collectioin("article").where({
    author: "北京日报"
}).count().then(res => {
    console.log(res);
});
collection.orderBy:

方法接受一个必填字符串参数fieldName用于定义需要排序的字段,一个字符串参数order定义排序顺序。order只能取 ascdesc

如果需要对嵌套字段排序,需要用 “点表示法” 连接嵌套字段,比如author.age表示字段author里的嵌套字段age
同时也支持按多个字段排序,多次调用orderBy即可,多字段排序时的顺序会按照orderBy调用顺序先后对多个字段排序。
比如我想通过阅读量从大到小以及作者的年龄从小到大进行排序。那么可以使用以下代码来实现:

db.collection("article")
    .orderBy("read_count","desc")
    .orderBy("author.age","asc")
    .get()
    .then(res => {
        console.log(res);
    })
collection.limit:

指定查询结果集数量上限。比如一次性获取10篇文章,那么可以通过以下代码来实现:

const db = wx.cloud.database()
db.collection(‘article’).limit(10)
.get()
.then(res => {
console.log(res);
})

collection.skip:

指定查询返回结果时从指定序列后的结果开始返回,常用于分页。比如跳过前面10篇文章,从第11篇开始获取。代码如下:

const db = wx.cloud.database()
db.collection('todos').skip(10)
  .get()
  .then(console.log)
  .catch(console.error)
collection.field:

指定返回结果中记录需返回的字段。比如只想获取article文章中的title字段。那么可以使用以下代码来实现:

const db = wx.cloud.database()
db.collection('todos').field({
  title: true
})
  .get()
  .then(console.log)
  .catch(console.error)
正则表达式:

从基础库2.3.2开始(wx-server-sdk0.0.23开始),数据库支持正则表达式查询,开发者可以在查询语句中使用 JavaScript原生正则对象或使用db.RegExp方法来构造正则对象然后进行字符串匹配。在查询条件中对一个字段进行正则匹配即要求该字段的值可以被给定的正则表达式匹配,注意正则表达式不可用于db.command内(如db.command.in)。

第八节:文件操作

请参考

第九节:node环境搭建

node环境搭建

因为云函数在服务器上实际上是运行在node.js环境中的,并且云函数是专门用来处理一些逻辑的,所以难免要用到一些第三方库,而云函数在编写的过程中,是需要先在本地写好,然后再进行提交到云服务器上。因此我们本地也需要安装好一套node.js环境。

nvm安装:

nvm(Node Version Manager)是一个用来管理node版本的工具。我们之所以需要使用node,是因为我们需要使用node中的npm(Node Package Manager),使用npm的目的是为了能够方便的管理一些前端开发的包!nvm的安装非常简单,步骤如下:

  1. 到这个链接下载nvm的安装包
  2. 然后点击一顿下一步,安装即可!
  3. 安装完成后,还需要配置环境变量。在我的电脑->属性->高级系统设置->环境变量->系统环境变量->Path下新建一个,把nvm所处的路径填入进去即可!
  4. 打开cmd,然后输入nvm,如果没有提示没有找不到这个命令。说明已经安装成功!
  5. Mac或者Linux安装nvm请看这里。也要记得配置环境变量。

nvm常用命令:

  1. nvm install latest:安装最新版的node.js。nvm i == nvm install。
  2. nvm install [version]:安装指定版本的node.js 。
  3. nvm use [version]:使用某个版本的node。
  4. nvm list:列出当前安装了哪些版本的node。
  5. nvm uninstall [version]:卸载指定版本的node。
  6. nvm node_mirror [url]:设置nvm的镜像。
  7. nvm npm_mirror [url]:设置npm的镜像。
node安装:

安装完nvm后,我们就可以通过nvm来安装node了。根据小程序中,云函数使用的node.js版本,来选择你要安装的版本。因为目前我的云函数用到的node.js版本是8.9.0,因此这里我们安装8.9.0版本的的node.js就可以。安装命令如下:

nvm install 6.4.0

如果你的网络够快,那以上命令在稍等片刻之后会安装成功。如果你的网速很慢,那以上命令可能会发生超时。因为node的服务器地址是https://nodejs.org/dist/,这个域名的服务器是在国外。因此会比较慢。因此我们可以设置一下nvm的源。

nvm node_mirror https://npm.taobao.org/mirrors/node/
nvm npm_mirror https://npm.taobao.org/mirrors/npm/
npm:

npm(Node Package Manager)在安装node的时候就会自动的安装了。当时前提条件是你需要设置当前的node的版本:nvm use 8.9.0。然后就可以使用npm了.
关于npm常用命令以及用法,请看下文。

安装包:

安装包分为全局安装和本地安装。全局安装是安装在当前node环境中,在可以在cmd中当作命令使用。而本地安装是安装在当前项目中,只有当前这个项目能使用,并且可以通过require引用。安装的方式只有-g参数的区别:

npm install express          # 本地安装
npm install express -g   # 全局安装
本地安装

将安装包放在./node_modules下(运行 npm 命令时所在的目录),如果没有node_modules目录,会在当前执行npm命令的目录下生成node_modules目录。
可以通过require()来引入本地安装的包。

全局安装

将安装包放在/usr/local下或者你node的安装目录。
可以直接在命令行里使用。

卸载包:
npm uninstall [package]
更新包:
npm update [package]
搜索包:
npm search [package]
使用淘宝镜像:
npm install -g cnpm --registry=https://registry.npm.taobao.org 

那么以后就可以使用cnpm来安装包了!

第十节:云函数

初始化环境:

wx小程序笔记(2)_第23张图片
在以上文件夹中,右键->初始化环境即可。

创建云函数:

cloudfunctions文件夹上,右键->创建云函数,填入云函数的名称,然后点击确定即可创建好。然后就可以在相应的index.js文件中写代码了。示例代码如下:

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const x = event.x;
  const y = event.y;

  return {
    result: x + y
  }
}
上传和部署:

在本地创建完云函数后,还只是在本地,所以还需要上传到服务器和部署。上传和部署非常简单,我们只需要在相应的函数的文件夹上,右键->上传并部署:云端安装依赖即可。

在云函数中操作数据库:

在云函数中,操作数据库,包括文件的操作,可以通过wx-server-sdk来实现。但是这个sdk与小程序端的API有以下两点不同:

  1. 服务端的API仅支持Promise风格调用。
  2. 服务端API可以进行批量的updateremove操作。

第十一节:检测内容安全

云函数检测内容安全

在我们的小程序,有时候需要让用户提交一些文字信息。但是对于用户提交的文字信息是否安全(反国家言论等),我们不得而知,因此需要对用户上传的数据进行一些检测。小程序中已经提供了这样的API,我们直接调用就可以了。

先获取AppID和AppSecret:

在检测过程中,我们需要先获取AppIDAppSecret,这两个参数可以在微信公众平台(小程序后台)->开发->开发设置中获取到。示例图如下:
wx小程序笔记(2)_第24张图片

获取access_token:

向这个https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET发送GET请求,把AppIDAppSecret都替换为之前获取的。返回回来的结果如下:

属性 类型 说明
access_token string 获取到的凭证
expires_in number 凭证有效时间,单位:秒。目前是7200秒之内的值。
errcode number 错误码
errmsg string 错误信息
获取结果:

在以上拿到access_token后,再向https://api.weixin.qq.com/wxa/msg_sec_check?access_token=ACCESS_TOKEN发送POST请求,并且把ACCESS_TOKEN替换为之前获取到的,在发送这个请求的时候还需要携带content参数,这个参数就是需要检验的文本内容。

第十二节:图片鉴黄

对于用户上传上来的图片,我们需要验证是否涉黄,如果有涉黄,就需要隐藏掉或者删掉,以免小程序或者公司被有关部门谈话。

流程:

  1. 进入https://cloud.tencent.com/,然后点击“智能鉴黄”。
    wx小程序笔记(2)_第25张图片

  2. 点击开通:
    wx小程序笔记(2)_第26张图片

  3. 进入快速开始文档https://cloud.tencent.com/product/pornidentification/getting-started

  4. 开通云API秘钥:
    点击访问管理,来到界面
    wx小程序笔记(2)_第27张图片
    然后再点击“继续操作”,再点击“新建秘钥”。
    wx小程序笔记(2)_第28张图片

  5. 进入到智能鉴黄SDK文档中https://cloud.tencent.com/document/product/864/18708。代码如下:

// 云函数入口文件
const { ImageClient } = require("image-node-sdk");

let AppId = '1253230774'; // 腾讯云 AppId
let SecretId = 'AKID5D7sUBg47wlaGoIIL0YoqGWaULsJP8Tf'; // 腾讯云 SecretId
let SecretKey = 'ALOLD7Ufjnhc5Pbxe6zg8MLPE2bk4A2f'; // 腾讯云 SecretKey

// 云函数入口函数
exports.main = async (event, context) => {
  const imageUrl = event.imageUrl;
  let imgClient = new ImageClient({ AppId, SecretId, SecretKey }); 
  try{
    return await imgClient.imgPornDetect({
      data: {
        url_list: [imageUrl]
      }
    })
  }catch(e){
    console.log(e)
  }
}
  1. 鉴黄API文档(保存了返回值):https://cloud.tencent.com/document/product/864/17609

第十三节:用户授权

用户授权

在云开发中,登录的概念被弱化了,取而代之的是授权功能,比如你想在小程序中发布一条微博,那么小程序必须要获取到你的相关的信息,比如微信昵称,头像,城市等。这时候就需要你授权给这个小程序。

过期的授权方式:

在之前的小程序版本中,只要调用wx.getUserInfo,微信就会自动弹出一个授权的界面,然后就可以获取用户的信息了。但是随着改版,这个接口只能是在已经被授权的情况下才能调用成功。官方文档如下:https://developers.weixin.qq.com/community/develop/doc/0000a26e1aca6012e896a517556c01。

新的授权方式:

新的授权方式要分两步走,第一步是进行用户的授权,第二步才是去调用wx.getUserInfo获取用户的信息。这两步的走法分别是:

  1. 专门写一个授权的页面,在这个页面中需要有一个button组件,并且他的open-type=‘getUserInfo’。示例代码如下:
 <button type="primary" open-type="getUserInfo" bindgetuserinfo="onGetUserInfoTap">
 授权button>

当用户点击这个按钮的时候,就会弹出一个授权对话框,当用户点击了授权后,就会执行onGetUserInfoTap的方法,然后把用户相关的信息返回回来。

  1. 获取用户信息:在第一次授权后,以后如果小程序没有被删掉,那么授权信息是一直保存在小程序中。所以下次再进入到小程序中的时候,我们可以在app.js中先判断一下有没有授权过,如果已经授权了,那么就可以获取用户的信息了。示例代码如下:
 loadUserInfo: function(){
   const that = this;
   wx.getSetting({
     success: res => {
       const isUserInfo = res.authSetting['scope.userInfo'];
       if(isUserInfo){
         wx.getUserInfo({
           success: res => {
             const userInfo = res.userInfo;
             that.globalData.userInfo = userInfo;
           }
         })
       }
     }
   })
 }

第十四节:其他授权方式

其他授权方式

获取用户信息的授权比较独特,有自己的一套授权方式。但是其他的数据授权,则又是另外一种方式。以下讲下基本的授权流程。

在app.json中配置:

如果需要授权某方面的数据,比如获取用户的地理位置,那么需要先在app.json中配置好permission字段。拿地理位置为例,示例代码如下:

{
  ...
  "permission": {
      "scope.userLocation": {
        "desc": "你的位置将用于微博的展示"
      }
    }
  ...
}

其中的desc将用于在获取用户授权的时候的提示性话语。

授权:

如果用户没有授权过某方面的数据,那么需要先调用wx.authorize来进行授权。示例代码如下:

wx.authorize({
  scope: "scope.userLocation",
  success: res => {
    // 做些授权过后的事情
  }
})
获取数据:

在授权完成后,就可以获取相关数据了。比如选择位置。示例代码如下:

wx.chooseLocation({
  success: res => {
    delete res.errMsg;
    that.setData({
      location: res
    })
  }
})

你可能感兴趣的:(笔记,前端)