> For the complete documentation index, see [llms.txt](https://gb.akanote.cn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gb.akanote.cn/wechat/base.md).

# Part1-语法入门

## 今日学习目标

1、熟悉APPID与微信开发者工具使用

2、熟练配置项目与沉浸式导航栏

3、掌握数据绑定并能实现双向数据绑定

4、掌握列表渲染与条件渲染

5、了解模板使用

6、掌握WXS的使用

7、掌握组件化开发、组件传值方法

8、掌握路由跳转与tabbar页面跳转

9、掌握生命周期

10、掌握数据请求及封装

## 预：微信小程序账号注册与APPID获取【了解】

访问 <http://mp.weixin.qq.com/> ，并点击 `立即注册` :

[![](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmbmufnj31eq0u0dne.jpg)](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmbmufnj31eq0u0dne.jpg)

点击：

[![](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmm42ylj31i60u079t.jpg)](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmm42ylj31i60u079t.jpg)

然后填写邮箱和密码（记住：如果你的邮箱注册过微信公众号，请重新注册一个邮箱）：

[![](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmi1co7j31bi0u079o.jpg)](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmi1co7j31bi0u079o.jpg)

点击注册，并且登录邮箱去激活：

[![](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmjkj3jj31m60u0wid.jpg)](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmjkj3jj31m60u0wid.jpg)

到邮箱中点击激活链接：

[![](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmdwam7j32is0u0dlz.jpg)](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmdwam7j32is0u0dlz.jpg)

跳转到小程序官网后：

[![](https://tva1.sinaimg.cn/large/008eGmZEly1gopmm91fo3j31eq0u0dne.jpg)](https://tva1.sinaimg.cn/large/008eGmZEly1gopmm91fo3j31eq0u0dne.jpg)

选择“个人”，然后按照要求填写：

[![](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmf4b7dj31de0u07a1.jpg)](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmf4b7dj31de0u07a1.jpg)

扫码确认后，点击继续：

[![](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmksiwaj31g80u0442.jpg)](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmksiwaj31g80u0442.jpg)

点击确定，就会跳转到小程序后台，这时候，点击左侧“开发”，再点击Tab栏“开发设置”，就可以获取到APPID了：

[![](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmgmzjbj31mi0u0q9s.jpg)](https://tva1.sinaimg.cn/large/008eGmZEly1gopmmgmzjbj31mi0u0q9s.jpg)

这个APPID只有自己能用，其他人是无法使用的。

## 一、微信小程序官网【了解】

<https://mp.weixin.qq.com/>

## 二、APPID注册【了解】

从官网这里进去：

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqiwdqawj31j50u0n83.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqiwdqawj31j50u0n83.jpg)

选择小程序进行注册：

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqiltitwj31j10u0ahn.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqiltitwj31j10u0ahn.jpg)

然后按照流程，填写好账号密码等信息即可。

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqixf4g3j31j20u07a0.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqixf4g3j31j20u07a0.jpg)

若在填写过程中，需要你选择企业类型，请选择个人。

如果依然不知道要怎么操作，请查看《[微信小程序账号注册与APPID](https://github.com/Macharf/aka-note/blob/main/note/wechat/微信小程序账号注册与APPID.md)》

## 三、获取APPID【掌握】

注册后，回到登录界面，登录刚刚注册的账号，进入系统后台，找到左侧的 `开发`：

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqiiuoicj31j10u0ahn.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqiiuoicj31j10u0ahn.jpg)

虽然我们的小程序在学习阶段，可以用测试号进行开发，但我们后期需要用到云开发，云开发要求必须有appid，因此，请尽快注册。

## 四、创建项目【掌握】

打开 `微信开发者工具`（下载地址：<https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html），扫码后进入到这个界面：>

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqk9q6baj31890u0tau.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqk9q6baj31890u0tau.jpg)

点击此处，新建项目，按照以下图示填选：

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqkz663xj31d30u04bz.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqkz663xj31d30u04bz.jpg)

点击 `新建`，创建成功，进入到以下界面：

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqir74tfj31d30u0gvz.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqir74tfj31d30u0gvz.jpg)

若未能进入此页面，请按快捷键 `ctrl+R` 重新编译一次即可。

## 五、工具与目录介绍【了解】

### 1、开发工具介绍

工具使用方法听讲师讲述即可。

### 2、目录介绍

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqipercwj31d30u0qk7.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqipercwj31d30u0qk7.jpg)

我们先学习静态页面开发，再深入学习云开发。因此，我们目前只需要关注 `miniprogram` 目录下的内容即可。

## 六、项目总配置文件【重点】

打开 `app.json` 后，我们可以看到，所有的页面的创建，都在 `pages` 这个数组中填写：

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqj0mn59j31d30u04hp.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqj0mn59j31d30u04hp.jpg)

其中，哪个页面地址写在数组的第一项，编译/刷新整个浏览器时，哪个页面就会优先显示。

### 1、创建页面

这里我们把pages下，所有页面都删掉，把这个 `pages` 字段也清空，我们自己来书写一个页面：

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqkvxht9j31d30u04bz.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqkvxht9j31d30u04bz.jpg)

### 2、沉浸式导航栏

与 `pages` 同级的 `window` 对象，可用于控制整个小程序的沉浸式导航栏，但每个 页面也可单独配置。我们先配置整个小程序试试：

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqiuaeraj31d30u04cc.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqiuaeraj31d30u04cc.jpg)

### 3、tabBar配置【重点】

这里提供tabbar配置所需要的图片：

链接: <https://pan.baidu.com/s/1ZtYFpuE2HoacIKikyMeUnw> 提取码: dm3i

在 `app.json` 中，`windows` 同级的位置，写入：

```json
{
  "windows": {
    ...
  },
  "tabBar": {
    "color": "#909192",
    "selectedColor": "#0600B8",
    "list": [{
      "pagePath": "pages/home/home",
      "text": "首页",
      "iconPath": "images/bar/bar1_1.png",
      "selectedIconPath": "images/bar/bar1.png"
    },{
      "pagePath": "pages/menu/menu",
      "text": "菜单",
      "iconPath": "images/bar/bar2_2.png",
      "selectedIconPath": "images/bar/bar2.png"
    },{
      "pagePath": "pages/new/new",
      "text": "新品",
      "iconPath": "images/bar/bar3_3.png",
      "selectedIconPath": "images/bar/bar3.png"
    },{
      "pagePath": "pages/kefu/kefu",
      "text": "小二",
      "iconPath": "images/bar/bar4_4.png",
      "selectedIconPath": "images/bar/bar4.png"
    }]
  }
}
```

这里路径不允许使用 `./` 开头。来看看效果：

[![](https://tva1.sinaimg.cn/large/008i3skNgy1gtfjp8hxxtj61d30u0jw802.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqn1e4eaj31d30u0tqd.jpg)

## 七、配置Home页面【重点】

打开 `home.json` 文件，我们尝试隐藏导航栏：

[![](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqkychv1j31d30u04bz.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqkychv1j31d30u04bz.jpg)

## 八、页面文件介绍【掌握】

`pages` 目录下，每个页面就是一个文件夹，一个页面包含wxml、wxss、js和json文件，其中：

* wxml：相当于html文件
* wxss：相当于css文件

### 1、标签

标签分单双标签，书写格式与html完全一样，但在微信小程序里，没有div、span、p、h1-h6这些标签，它只有非常简单的两个最基本的标签：**view**(即：div) 与 **text**(即：span)。当然，还有其他经过封装的组件，我们后面会再做介绍。

### 2、JavaScript

微信小程序与vue.js框架用法大致相同，同属MVVM框架，都是由数据驱动视图更新。因此，js事件和变量的书写，也会与原生JS稍有差异。

## 九、数据绑定【重点】

在 `home.wxml` 页面写入：

```html
<view>{{msg}}</view>
```

在 `home.js` 写入：

```js
Page({
  data: {
    msg: '你好，世界'
  }
})
```

如此，便完成了数据绑定。

可以看到，动态变化的数据，我们统一放在data里面。这里跟vue做个区别，vue中规定组件内data必须是函数，而小程序不用，使用一个对象表示即可。

小程序中，我们要记住，凡是调用data中的数据，在wxml文件使用时，就需要加 `{{}}`，这语法便是著名的：mustache语法，也称胡子语法。

## 十、双向数据绑定【重点】

### 1、修改data中的数据

小程序中，使用 `this.setData()` 来修改data中的数据。

### 2、方法绑定

一个标签需要调用一个函数（或称：方法），需要在标签上绑定事件，如绑定触摸事件（即：pc上的点击事件）：

```html
<button bindtap="tapFn">按钮</button>
```

然后在js中：

```js
Page({
  data: {
    ...
  },
  tapFn(){
    // do something...
  }
})
```

### 3、实现双向数据绑定

我们来实现双向数据绑定：

在 `home.wxml` 中：

```html
<input value="{{msg}}" bindinput="iptFn"></input>
<view>{{msg}}</view>
```

在js中：

```js
Page({
  data: {
    msg: '你好，世界'
  },
  // input值被修改时触发的函数
  iptFn(e){
    this.setData({
      msg: e.detail.value
    })
  }
})
```

## 十一、列表循环【重点】

微信小程序实现for循环有好几种方式，一种是使用block标签来循环一段代码，当然，也可以直接在要循环的那段代码的外层，直接进行 `wx:for` ，看个人喜好。

```html
<!-- 方法1 -->
<view class="box">
    <view wx:for="{{arr}}" wx:key="*this">{{item}}</view>
</view>

<!-- 方法2 -->
<view class="box">
    <block wx:for="{{arr}}" wx:key="*this">
      <view>{{item}}</view>
    </block>
</view>
```

js中：

```js
Page({
  data: {
    arr: ['张三', '李四', '王五']
  }
})
```

可以复制以上代码，到模拟器看看效果，会发现原来效果一样。

**这里要注意几点：**

1. wx:key可以不写，但不写会报黄色警告；
2. 保留关键字 `*this` 代表在 for 循环中的 item 本身，这种表示需要 item 本身是一个唯一的字符串或者数字；
3. 每个循环都会自带 `item` 与 `index` ，不需要像vue一样写：`v-for="(item, index) in arr"`；
4. 如果出现多层数组的循环，那就会出现item指向不明确，虽然小程序可以帮我们自动识别，但代码可维护性降低，因此，我们可以使用 `wx:for-item="items"` 来改变item的名称。

## 十二、条件渲染【重点】

### 1、wx:if

在框架中，使用 `wx:if=""` 来判断是否需要渲染该代码块：

```html
<view wx:if="{{condition}}"> True </view>
```

也可以用 `wx:elif` 和 `wx:else` 来添加一个 else 块：

```html
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
```

### 2、block wx:if

因为 `wx:if` 是一个控制属性，需要将它添加到一个标签上。如果要一次性判断多个组件标签，可以使用一个 `标签将多个组件包装起来，并在上边使用 wx:if` 控制属性。

```html
<block wx:if="{{true}}">
  <view> view1 </view>
  <view> view2 </view>
</block>
```

**注意：** `block` 并不是一个组件，它仅仅是一个包装元素，不会在页面中做任何渲染，只接受控制属性。

### 3、`wx:if` vs `hidden` 【了解】

因为 `wx:if` 之中的模板也可能包含数据绑定，所以当 `wx:if` 的条件值切换时，框架有一个局部渲染的过程，因为它会确保条件块在切换时销毁或重新渲染。

同时 `wx:if` 也是**惰性的**，如果在初始渲染条件为 `false`，框架什么也不做，在条件第一次变成真的时候才开始局部渲染。

相比之下，`hidden` 就简单的多，组件始终会被渲染，只是简单的控制显示与隐藏。

一般来说，`wx:if` 有更高的切换消耗而 `hidden` 有更高的初始渲染消耗。因此，如果需要频繁切换的情景下，用 `hidden` 更好，如果在运行时条件不大可能改变则 `wx:if` 较好。

### 4、总结

`hidden` 属性用于频繁切换，切换较少时，建议使用 `wx:if`。用法：

wxml中：

```html
<view hidden="{{ifShow}}">显示或隐藏</view>
```

js中：

```js
Page({
  data: {
    ifShow: false	// 由于hidden代表一种否定（或称：取反），所以这里为false，上面的view标签才能显示
  }
})
```

## 十三、模板与引用【熟悉】

vue中有插槽的概念，小程序中有模板与引用，这两者还是比较像的。我们先来看看怎么玩。

### 1、模板创建

在 `pages/home/` 目录下创建 `templates` 文件夹，里面用于存放模板文件。我们新建 `item.wxml` 文：

```html
<template name="box1">
  <text bindtap="txtFn">box1: {{content}}</text>
</template>

<template name="box2">
  <text bindtap="txtFn">box2: {{content}}</text>
</template>
```

### 2、模板引用

在 `home.wxml` 中：

```html
<import src="./templates/item.wxml" />
<template is="box1" data="{{content: txt}}"></template>
```

这里通过import标签引入模板，通过template标签使用模板，使用is属性来指定调用 `item.wxml` 中哪个模板，使用data属性来传值。

这里大家要注意，创建模板时，我们写的 `bindtap="txtFn"` ，实现txtFn的方法，需要写在 `调用方` 的js文件中，而非模板的js文件。

```js
// home.js
Page({
  data: {
    txt: '叩丁狼H5大前端'
  },
  // 可供模板调用的方法
  txtFn(){
    console.log('打印...')
  }
})
```

## 十四、WXS模块【掌握】

WXS 代码可以编写在 wxml 文件中的 `<wxs>` 标签内，或以 `.wxs` 为后缀名的文件内。

WXS（WeiXin Script）是小程序的一套脚本语言，结合 WXML，可以构建出页面的结构。

wxs可以说就是为了满足能在页面中使用js存在的，在wxml页面中，只能在插值 `{{ }}` 中写简单的js表达式，而不能调用方法，例如想取出一个字符串的最后一位，就不能调用slice()方法。

通常的解决办法是在page的data对象中先把这个字符串截取好赋给某个变量，然后在页面中使用这个变量，但是问题又来了，如果变量多了呢，是不是要定义很多次？wxs就是弥补了这样的短处。

相对来说wxml中使用js语法就比较薄弱了，wxs就是弥补了这样的短处。

### 1、使用方法

* 写好wxs文件 然后使用 `module.exports` 导出要使用的方法或变量
* 在待使用页面 使用 `<wxs src="/path" module="tools" />` 引入
* 在插值语法中使用 `tools.method_name(para)`

### 2、实用教程

#### \* wxs写法1

在 `home` 页面下，新建 `test.wxs` ，并写一段截取字符串的方法：

```js
function my_slice(str,a,b){
  return str.slice(a,b);
}
module.exports = {
  my_slice: my_slice
}
```

在wxml文件：

```html
<wxs src="./test.wxs" module="tools" />
<view>
  {{tools.my_slice("123456789",0,5)}}
</view>
```

#### \* wxs写法2

在wxml文件：

```html
<wxs module="tools">
  function add(a, b){
    var sum = a + b;
    return sum;
  }
  module.exports = {
    add: add
  };
</wxs>

<view>
  {{tools.add(3, 4)}}
</view>
```

## 十五、组件化开发【重点】

接下来的首页“新品展示”区块，我们采用组件化开发的操作：

### 1、创建组件

组件相当于页面，创建的方法与创建页面相同，可以在 `app.json` 中的 `pages` 进行创建：

```json
{
  "pages": [
    ...,
    "components/product/product"
  ],
}
```

我们看到，在项目根目录中，增加了一个 `components/product/product` 目录。

### 2、结构、样式与数据渲染

`product.wxml` 中：

```html
<view class="product_list">
  <view wx:for="{{showArr}}" wx:key="*this" class="product_list_box">
    <image src="{{item.imgSrc}}" mode="widthFix"></image>
    <view>{{item.imgTxt}}</view>
  </view>
</view>
```

`product.wxss` 中：

```css
/* components/product/product.wxss */
.product_list{
  display: flex;
  padding: 20rpx 2%;
  justify-content: space-between;
  flex-wrap: wrap;
}

.product_list_box{
  width: 49%;
  box-shadow: 0 0 6rpx #666;
  border-radius: 10rpx;
  overflow: hidden;
  margin-bottom: 20rpx;
}

.product_list_box image{
  width: 100%;
  display: block;
}

.product_list_box view{
  height: 50rpx;
  line-height: 50rpx;
  text-align: center;
}
```

`product.js` 中：

```js
// 注意注意：这里的Page()方法改成了Component()方法
Component({
  data: {
    showArr: [
      {imgSrc: "/images/home/newPro1.jpg", imgTxt: "卡布奇诺"},
      {imgSrc: "/images/home/newPro2.jpg", imgTxt: "白咖啡"},
      {imgSrc: "/images/home/newPro3.jpg", imgTxt: "摩卡咖啡"},
      {imgSrc: "/images/home/newPro4.jpg", imgTxt: "爱尔兰咖啡"},
      {imgSrc: "/images/home/newPro5.jpg", imgTxt: "甜品咖啡"},
      {imgSrc: "/images/home/newPro6.jpg", imgTxt: "意大利咖啡"},
      {imgSrc: "/images/home/newPro7.jpg", imgTxt: "拿铁咖啡"},
      {imgSrc: "/images/home/newPro8.jpg", imgTxt: "中式咖啡"}
    ]
  },
})
```

### 3、声明为组件

在 `product.json` 中：

```json
{
  "usingComponents": {},
  "component": true
}
```

### 4、调用组件

在 `home.json` 中：

```json
{
  "usingComponents": {
    "product-block": "/components/product/product"
  },
  "navigationStyle": "custom"
}
```

在 `home.wxml` 中：

```html
<product-block />
或：
<product-block></product-block>
```

## 十六、组件传值【重点】

虽然此时我们已经完成了组件化开发并引入成功，但我们要考虑数据是否放在子组件中，很明显这个子组件可能将来会被复用，因此数据应该由父级获取后传给子级，这样更加稳妥些。

### 1、父传子

我们将该组件的数据迁移到父组件 `Home.js` 中，然后通过父传子传过来：

`Home.wxml` 中：

```html
<product-block showArr="{{showArr}}" />
```

`product.js` 中：

```js
Component({
  // properties用于接收传值，类似于vue中的props
  properties: {
    showArr: {
      // 设置数据类型
      type: Array,
 			// 设定初始值（即默认值）
      value: [{imgSrc: "/images/home/newPro1.jpg", imgTxt: "卡布奇诺"}]
    }
  }
})
```

### 2、子传父

我们尝试点击 `product` 组件中的任意一项，来触发父级的事件。

```html
<!-- 子组件wxml -->
<view class="product_list">
  <view wx:for="{{showArr}}" wx:key="*this" class="product_list_box" bindtap="productTap">
    ...
  </view>
</view>
```

```js
// components/product/product.js
Component({
  ...,
  // 如果是组件，不是页面，就必须写methods
  methods: {
    productTap(){
  		// 小程序中子传父通过triggerEvent来实现
      this.triggerEvent('fatherEvent', 100);
    }
  }
})
```

父组件：

```html
<!-- 标签上使用bind来接收子组件传过来的事件 -->
<product-block showArr="{{showArr}}" bind:fatherEvent="fatherEventFn" />
```

```js
Page({
  ...,
  // 页面无需写methods
  fatherEventFn(data){
    console.log(data.detail); // 100
  }
})
```

如此，我们实现了父子传值。

### 3、全局变量globalData

微信小程序全局变量globalData在app.js中，调用的方法有：

【方法一(推荐)】通过app获取，需要在第一行声明app的实例 const app = getApp()

```js
const app = getApp()
Page({
  onLoad: function () {
    console.log(app.globalData.name);
  },
})
```

【方法二】直接通过getApp().globalData获取，不需要写const app = getApp()实例

```js
onLoad: function () {
    console.log(getApp().globalData.name);
},
```

【方法三】在app.js文件内使用

```js
onLoad: function () {
    console.log(this.globalData.name);
},
```

修改global的方法【借助方法一】：

```js
app.globalData.name = "xxxx";
```

## 十七、路由跳转【掌握】

### 1、跳转到非tabbar页面(js)

```js
wx.navigateTo({
    url: '/pages/logs/logs'
})

// url携带参数的形式：
wx.navigateTo({
    url: '/pages/logs/logs?id=123',
})

// 如何获取参数？
onLoad: function (options) {
    console.log(options.id)		// 123
},
    
// 携带复杂参数的形式
wx.navigateTo({
    url: '/pages/logs/logs?id=123',
    success: function(res) {
        // 通过eventChannel向被打开页面传送数据
        res.eventChannel.emit('someData', { arr: [1,2,3] })
    }
})

// 接收复杂参数的形式
onLoad: function (options) {
    console.log(options.id)		// 123
    const eventChannel = this.getOpenerEventChannel()	// 通过eventChannel来获取参数
    eventChannel.on('someData', function(data) {
        console.log(data.arr)	// [1,2,3]
    })
},
    
// 当前页反向发射数据到上一页
onLoad: function (options) {
    const eventChannel = this.getOpenerEventChannel()
    // 反向发射数据
    eventChannel.emit('fanxiang', {username: '张三'});
},
    
// 上一页接收反向发射的数据
wx.navigateTo({
    url: '/pages/list/list?id=123',
    // events中写反向发射的函数
    events: {
        fanxiang(data){
            console.log(data)
        }
    }
})
```

### 2、跳转到非tabbar页面(wxml)

```html
<navigator url="/pages/logs/logs"></navigator>
```

### 3、跳转到tabbar页面

```js
wx.switchTab({
    url: '/pages/user/user'
})
```

## 十八、生命周期【重点】

微信小程序有两类生命周期，一类是[组件的生命周期](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/lifetimes.html)，另一类是[页面的生命周期](https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/page-life-cycle.html)。

### 1、页面的生命周期：

[![img](https://tva1.sinaimg.cn/large/008i3skNgy1gtfjnrkay9j60ie0s6abu02.jpg)](https://tva1.sinaimg.cn/large/008i3skNly1gsoelg0s86j30ie0s6jt6.jpg)

总的来说，小程序页面的生命周期为：

**onLoad** > **onShow** > **onReady** > **onHide** > **onShow** > **onUnload**

### 2、组件生命周期

组件的生命周期：

```js
Component({
  lifetimes: {
    attached: function() {
      // 在组件实例进入页面节点树时执行
    },
    detached: function() {
      // 在组件实例被从页面节点树移除时执行
    },
  }
})
```

这里提供组件的生命周期表：

| 生命周期     | 参数             | 描述                   | 最低版本                                                                                   |
| -------- | -------------- | -------------------- | -------------------------------------------------------------------------------------- |
| created  | 无              | 在组件实例刚刚被创建时执行        | [1.6.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) |
| attached | 无              | 在组件实例进入页面节点树时执行      | [1.6.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) |
| ready    | 无              | 在组件在视图层布局完成后执行       | [1.6.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) |
| moved    | 无              | 在组件实例被移动到节点树另一个位置时执行 | [1.6.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) |
| detached | 无              | 在组件实例被从页面节点树移除时执行    | [1.6.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) |
| error    | `Object Error` | 每当组件方法抛出错误时执行        | [2.4.1](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) |

这里有个要注意的点：

> 官方文档：
>
> 组件实例刚刚被创建好时， `created` 生命周期被触发。此时，组件数据 `this.data` 就是在 `Component` 构造器中定义的数据 `data` 。 **此时还不能调用 `setData` 。** 通常情况下，这个生命周期只应该用于给组件 `this` 添加一些自定义属性字段。

可以看出，在created中无法使用this，因此，建议不在created中做请求

再提供组件所在页面的生命周期：

| 生命周期   | 参数            | 描述             | 最低版本                                                                                   |
| ------ | ------------- | -------------- | -------------------------------------------------------------------------------------- |
| show   | 无             | 组件所在的页面被展示时执行  | [2.2.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) |
| hide   | 无             | 组件所在的页面被隐藏时执行  | [2.2.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) |
| resize | `Object Size` | 组件所在的页面尺寸变化时执行 | [2.4.0](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) |

代码示例：

```js
Component({
  pageLifetimes: {
    show: function() {
      // 页面被展示
    },
    hide: function() {
      // 页面被隐藏
    },
    resize: function(size) {
      // 页面尺寸变化
    }
  }
})
```

## 十九、数据请求【重点】

### 1、原生API调用

在微信小程序中，我们使用 `wx.request()` 方法做数据请求，如：

```js
wx.request({
  url: 'http://kumanxuan1.f3322.net:8001',
  success(res){
    console.log(res);
  }
})
```

接口地址：

叩丁严选项目接口文档 <http://www.docway.net/project/1Ve70KqViGf/share/1Wi8PNyUmTA> 阅读密码:zhaowenxian

### 2、合法域名配置

正常来讲，按照以上操作会碰到合法域名的报错，如：

[![1618026295311](https://tva1.sinaimg.cn/large/008i3skNgy1gtfjjhedsnj61470ap0v002.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqmy8ltzj31470apdj4.jpg)

这是因为小程序对接口地址有严格要求，所有的baseUrl必须在小程序后台配置合法域名。

到 `mp.weixin.qq.com` 登录，找到 `开发` - `开发管理` - `开发设置` - `服务器域名` 。只需要将后端给你的接口地址填写进去即可。这里注意：合法域名必须是https开头，否则无法配置，只能作为开发阶段的测试。

开发阶段想要测试，可以点击开发工具右上角的 `详情` ：

[![1618026491334](https://tva1.sinaimg.cn/large/008i3skNgy1gtfjjgz2k6j61dn0u0n4202.jpg)](https://tva1.sinaimg.cn/large/008eGmZEgy1gpkqmsvldmj31dn0u0qdr.jpg)

将 `不校验合法域名` 勾选上即可。

### 3、request封装

使用资料中封装好的request，其中有三个文件：

> 这里提供资料获取链接：
>
> 链接: <https://pan.baidu.com/s/1BYzvpIbTlid_MLrh1RFA1g> 提取码: 7gsl

* `request.js` 是用来封装请求的，一般我们不动它
* `api.js` 是用来统一管理Restful风格的接口地址与baseUrl的
* `fetch.js` 是用来导出请求函数，供页面调用的，其中有3套模板，大家可以直接copy使用

## 二十、作业

参考 [【硬核干货】小程序+Weapp自定义TabBar](https://www.bilibili.com/video/BV1VU4y157nX/) 做出tabbar。
