微信小程序入门篇

1、概述

1.1 什么是微信小程序?

微信小程序,简称小程序,英文名Mini Program,是一种无需下载安装即可直接使用的应用,实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。

1.2 为什么是微信小程序?

  • 微信有大量的用户,在微信里开发产品更加容易触达用户;
  • 推广app或者公众号的成本太高;
  • 开发适配成本低;(以前开发app需要去适配不同的手机型号,十分繁琐,而开发小程序只需要按照小程序开发文档开发即可,微信会帮我们做好适配工作)
  • 容易小规模试错,便于快速迭代;
  • 跨平台(IOS/Andriod)

2、环境准备

在开发小程序之前,我们需要进行如下操作:

2.1 注册账号

访问微信公众平台进行账号注册,建议使用一个新的邮箱进行注册。
"D:\images\学习截图\小程序账号注册.png"

2.2 获取APPID

APPID是小程序开发者的“身份证”,当我们需要上线小程序或者使用小程序的高级功能的时候,必须提供APPID.获取步骤如下:

  • 使用刚刚注册的账号登录,也可以扫码登录,登陆成功会进入小程序界面;
  • 接着在左侧菜单找到开发-开发管理-开发设置
    "D:\images\学习截图\获取appid.png"

2.3 工具下载

访问下载地址下载微信开发者工具,无脑安装,使劲下一步即可。第一次打开软件需要扫码登录,界面如下所示:
"D:\images\学习截图\微信开发者工具界面.png"

不过这个工具编码体验不好,我们一般使用vscode进行编码,使用该工具进行预览。

3、第一个微信小程序

3.1 创建小程序

打开微信开发者工具,点击加号创建项目,填写相关信息即可创建:
"D:\images\学习截图\创建小程序.png"

3.2 小程序目录结构

小程序框架提供了自己的视图层描述语言wxmlwxss,以及javascript,并在视图层和逻辑层中提供了数据传输和事件系统,让开发者能够专注于数据和逻辑。

3.2.1 小程序文件和传统web对比
对比项传统小程序
结构htmlwxml
样式csswxss
逻辑jsjs
配置json
3.2.2 小程序项目目录结构

"D:\images\学习截图\项目目录结构.png"

3.3 小程序配置文件

小程序配置文件有两种:第一种是全局配置文件app.json,第二种是页面专属配置文件页面名.json.

3.3.1 全局配置文件
{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"dark",
    "navigationBarBackgroundColor": "#0094ff",
    "navigationBarTitleText": "我的小程序",
    "navigationBarTextStyle":"white",
    "enablePullDownRefresh": true,
    "backgroundColor":"#0094ff"
  },
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "icon/_home.png",
        "selectedIconPath": "icon/home.png"
      },
      {
        "pagePath": "pages/img/img",
        "text": "图片",
        "iconPath": "icon/_img.png",
        "selectedIconPath": "icon/img.png"
      },
      {
        "pagePath": "pages/mine/mine",
        "text": "我的",
        "iconPath": "icon/_my.png",
        "selectedIconPath": "icon/my.png"
      },
      {
        "pagePath": "pages/search/search",
        "text": "搜索",
        "iconPath": "icon/_search.png",
        "selectedIconPath": "icon/search.png"
      }
    ],
    "color": "#ff9400"
  },
  "style": "v2",
  "sitemapLocation": "sitemap.json"
}
  • 其中,pages里面是用来配置页面路径的,注意不需要加后缀。我们可以手动在里面输入一个页面路径,然后保存(注意是在微信开发者工具保存才会立即生效),然后会自动生成xxx.wxmlwxssjsjson文件;
  • 第二个windows是用来设置默认窗口表现的,比如导航栏的背景颜色、文字等;
    • navigationBarBackgroundColor:用于设置导航栏背景颜色;
      "D:\images\学习截图\导航栏.png"

    • navigationBarTitleText:用于设置导航栏的标题文字;

    • navigationBarTextStyle:用于设置导航栏标题文字的颜色,只能是black或者white;

    • enablePullDownRefresh:开启下拉刷新;

    • backgroundTextStyle:用于设置下拉的点点的样式,只支持darklight;

    • backgroundColor:这个不是页面的背景颜色,而是下拉的背景颜色

  • 第三个tabbar用于设置类似于手机淘宝的底部的tab栏,tabbar里的list属性是一个数组,用于配置最少两个tab,每个tab包含如下属性:
    • pagePath:用于配置本tab的页面路径;
    • text:用于配置本tab的提示文字;
    • iconPath:配置未被选中时的图标;
    • selectedIconPath:选中时的图标
      "D:\images\学习截图\底部导航.png"

tabbar还有其它的属性比如color用于设置文字颜色等请参考官网

3.3.2 页面配置文件

页面配置文件xxx.json用于单独配置某个页面,打开pages下的每个页面目录下的xxx.json即可进行编辑,很多属性和全局配置文件一样,可参考官网

4、模板语法

4.1 数据绑定

我们可以在xxx.js文件中的Page方法中的data中定义初始化数据,并且可以在xxx.wxml中使用Mustache语法(双大括号)进行使用。具体如下:

首先我们在demo01.js文件中定义数据:

Page({

  /**
   * 页面的初始数据
   */
  data: {
    "msg":"hello everybody",
    "num":10000,
    "isGirl":true,
    "person":{
      "name":"张三",
      "age":23
    },
    "isChecked":true
  }
})

接着在demo01.wxml中使用:

<!--
  text标签相当于html中的span标签
  view标签相当于html中的div标签
-->
<!--字符串-->
<text>{{msg}}</text>
<!--数字--> 
<text>{{num}}</text> 
<!--布尔-->
<view>你是一个女孩吗:{{isGirl}}</view>
<!--object-->
<view>{{person.name}}--{{person.age}}</view>
<!--用在属性上-->
<checkbox checked="{{isChecked}}" />

4.2 运算

我们可以在双大括号内进行简单的数值运算、字符串拼接和逻辑运算:

<!--数字运算-->
<view>{{1+1}}</view>
<!--字符串拼接-->
<view>{{'1'+'1'}}</view>
<!--逻辑运算-->
<view>{{1+1 === 3 ? "是的":"不是"}}</view>

4.3 遍历

遍历分为数组遍历对象遍历,首先需要在data里面添加一个数组和对象

 "person":{
      "name":"张三",
      "age":23
    },
    "list":[
      {
        "id":1,
        "name":"张三"
      },
      {
        "id":2,
        "name":"里斯"
      },
      {
        "id":3,
        "name":"王五"
      }
    ]

接着我们在wxml中使用wx:for来进行遍历:

<!--
  列表循环:
    wx:for="要遍历的数组或对象"
    wx:for-item="遍历项的名称"
    wx:for-index="遍历项的索引"
    wx:key用于提高列表渲染的性能,如果在遍历对象数组时,一般使用对象的具有唯一性的属性比如id
    如果是在遍历普通数组时比如[1,2,3,4],一般使用*this也就是其本身
-->
<view>
  <view wx:for="{{list}}" wx:for-item="item" wx:for-index="index" wx:key="id">
    索引:{{index}}
    ---
    名称:{{item.name}}
  </view>
</view>

<!--
  对象循环:
  索引是对象的属性名,遍历项是属性名对应的值
-->
<view>
  <view wx:for="{{person}}" wx:for-index="key" wx:for-item="value">
    {{key}}:{{value}}
  </view>
</view>

4.4 条件渲染

<!--
  条件渲染:
    1、wx:if wx:elif wx:else
    2、hidden
  区别:
    wx:if是从页面结构上移除某个标签,而hidden只是添加display样式为none
-->
<view wx:if="{{true}}">1</view>
<view wx:elif="{{false}}">2</view>
<view wx:else>3</view>

<view hidden="{{true}}">隐藏</view>
<view hidden="{{false}}">显示</view>

5、事件绑定

在微信小程序中,事件绑定通过bind关键字来实现,比如:bindinput、bindtap等。

5.1 输入绑定

需求:在data里面定义num,当输入值改变时,num也会同步改变:

  /**
   * 页面的初始数据
   */
  data: {
    num:0
  },
  //处理输入
  handleInput(e){
    this.setData({
      num: e.detail.value
    })
  },
<!--
  1、为输入框绑定输入事件,使用bind关键字+input事件类型
  2、获取输入的值:e.detail.value(e是事件源)
  3、将输入值和赋给num
    注意不能使用:this.data.num = e.detail.value
    需要使用:
    this.setData({
      num: e.detail.value
    })
-->
<input type="text" bindinput="handleInput" />
<view>{{num}}</view>

5.2 点击绑定

需求:当点击+,num会加1,当点击-,num也会减1

  //处理点击
  handleTap(e){
    const operation = e.target.dataset.operation
    this.setData({
      num: this.data.num + parseInt(operation)
    })
  }
<!--
  1、为两个按钮绑定点击事件:bind关键字+tap点击事件
  2、在小程序中无法直接传递参数,如下所示,因为它会连带参数当作是一个方法,所以会找不到该方法
  3、使用自定义属性来传递参数,自定义属性以`data-`为前缀,实际上的属性名是operation,我们
  可以在事件源中获取到自定义属性的值:e.target.dataset.operation
-->
<!-- <button bindtap="handleTap(1)">+</button>
<button bindtap="handleTap(-1)">-</button> -->
<button data-operation="1" bindtap="handleTap">+</button>
<button data-operation="-1" bindtap="handleTap">-</button>
<view>{{num}}</view>

6、样式wxss

wxss是微信小程序定义样式的文件,相当于css.

6.1 尺寸单位

rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。现在我们在wxml中创建一个view,我们希望它的宽度可以根据屏幕宽度的变化而变化,那我们就需要将它在设计稿上的宽度换算为rpx:

<view>
  haha
</view>
/* 小程序当中不需要主动引入样式文件 */
/*
  假设设计稿宽度为 750px,元素宽度为200 px,那么
  750 px = 750 rpx
  1 px = 1 rpx
*/
/* view{
  width: 200rpx;
  height: 200rpx;
  background-color: aqua;
} */

/*
  假设设计稿宽度为 未知 page,元素宽度为 200px,那么
  page px = 750 rpx
  1 px = 750 rpx / page

  200 px = 750 rpx * 200 / page
  假设page为414px
*/
view{
  width: calc(750rpx * 200 / 414);
  height: calc(750rpx * 200 / 414);
  background-color: aqua;
}

6.2 样式导入

在微信小程序中,如果需要导入外部样式表,需要通过@import进行导入。现在我们项目根路径下新建一个文件夹style,下面有一个common.wxss:

view{
  color: aqua;
  font-size: 18px;
}

接着我们在xxx.wxss中进行引入:

/*
注意引入只能是相对路径
*/
@import '../../style/common.wxss'

6.3 选择器

只需要注意一点,小程序中不支持*通配符,也就是说下面的代码是无法生效的:

*{
    margin:0;
    padding:0;
}

6.4 小程序中使用less

原生的微信小程序是不支持less,如果希望在小程序中使用less,可以按如下步骤进行:

  • 打开vscode安装插件的位置;
  • 搜索Easy Less进行安装;
  • 快捷键ctrl+shift+p搜索settings,打开settings.json加入如下代码:
    "less.compile": {
      "outExt": ".wxss"
    }
  • 接着就可以新建less文件并进行编辑了

我们新建一个界面,将里面的xxx.wxss的后缀改为less,然后就可以在里面写less代码了:

// 1、定义变量(注意:分号不可省略)
@color: green;
//2、使用变量
view {
  color:@color;
}

我们在编写完保存后会在目录下生成xxx.wxss,这个文件由上面的less文件编译而来:

view {
  color: green;
}

7、小程序的常用组件

7.1 view

前面已经说过,这个组件就相当于html中的div

7.2 text

text是文本标签,它里面也只能嵌套文本标签:

<!--
  1、selectable:长按文字是否可选
  2、decode:是否对内容进行解码(如果不进行解码处理,下面的会原样输出而不是显示空格)
-->
<text selectable decode>text&nbsp;111</text>

7.3 image

image是图片组件,和html的图片标签类似:

  • src:图片链接
  • mode:图片裁剪和缩放的模式,可选值参考官网
<image src="https://s3.ax1x.com/2021/02/02/yurkUH.png" />

7.4 swiper

swiper是微信小程序提供的轮播图组件。swiper的常用属性如下:

  • autoplay:是否开启自动切换;
  • circular:是否衔接滑动(在轮播项较少时不会看着别扭)
  • interval:设置轮播时间
  • indicator-dots:是否显示面板指示点,也就是那些小圆点
<!--
  1 swiper 轮播图的外层容器
  2 swiper-item 轮播项
  3 swiper存在默认样式 宽度 100% 高度 150px 并且高度无法被内容撑开 image也存在默认宽高 320*240
  4 如果希望图片可以占满整个swiper并且保持宽高比,那么必须满足下面的条件
    swiper 宽度 / swiper 高度 = 原图宽度 / 原图高度
    swiper高度 = swiper 宽度 * 原图高度 / 原图宽度 = 750rpx * 400 / 990
  5 mode="widthFix" 高度会根据宽度自动适应
-->
<swiper autoplay circular interval="2000" indicator-dots="{{true}}">
  <swiper-item><image mode="widthFix" src="https://img.alicdn.com/tfs/TB1ZLUmoZVl614jSZKPXXaGjpXa-990-400.jpg_q90.jpg" /></swiper-item>
  <swiper-item><image mode="widthFix" src="https://img.alicdn.com/tfs/TB16gBE17Y2gK0jSZFgXXc5OFXa-990-400.png_q90.jpg" /></swiper-item>
</swiper>
swiper{
  width: 100%;
  height: calc(750rpx * 400 / 990);
}
image{
  width: 100%;
}

7.5 navigator

navigator导航类似超链接标签。

<!--
  url:跳转的地址,可以是绝对路径也可以是相对路径
  target:在哪个目标上发生跳转,默认是当前小程序
  open-type:跳转方式
    - navigate:保留当前页面(也就是跳转后左上角会出现回退按钮),跳转到其他页面,但是无法跳转到tabbar页面
    - redirect:不保留当前页面,跳转到其它页面,同样无法跳转到tabbar页面
    - switchTab:不保留当前页面,跳转到tabbar页面,但是无法跳转到普通页面
-->
<navigator url="/pages/demo07/demo07" open-type="navigate">跳转到轮播图</navigator>
<navigator url="/pages/index/index" open-type="navigate">跳转到tabbar</navigator>
<navigator url="/pages/demo07/demo07" open-type="redirect">redirect 轮播图</navigator>
<navigator url="/pages/index/index" open-type="redirect">redirect tabbar</navigator>
<navigator url="/pages/index/index" open-type="switchTab">switchTab tabbar</navigator>
<navigator url="/pages/demo07/demo07" open-type="switchTab">switchTab 轮播图</navigator>

7.6 rich-text

rich-text是富文本组件。

<!--
  rich-text:
    nodes就是要显示的富文本内容,nodes既可以是html字符串,也可以是对象数组
-->
<rich-text nodes="{{html}}"></rich-text>
Page({

  /**
   * 页面的初始数据
   */
  data: {
    // html:'<div>hahah</div>',
    html:[
      {
        name:'div',//标签名
        attrs:{//属性
          style:'color:red;'
        },
        children:[//子节点
          {
            name:'p',
            attrs:{},
            children:[
              {
                type: 'text',
                text: 'hahaha'
              }
            ]
          }
        ]
      }
    ]
  }
})

7.7 button

7.7.1 按钮属性
<!--
  按钮属性:
  1 size
    - default 默认尺寸
    - mini 小尺寸
  2 type
    - default 白色
    - primary 绿色
    - warn 红色
  3 plain
      按钮是否镂空,背景色透明
  4 loading
      名称前是否带loading图标
-->
<button>默认按钮</button>
<button size="mini">mini按钮</button>
<button type="primary">primary按钮</button>
<button type="warn">warn按钮</button>
<button plain>plain按钮</button>
<button loading>loading按钮</button>
7.7.2 按钮的开放能力
<!--
  按钮的开放能力
  open-type:
    - contact:打开小程序的客服对话功能,需要在小程序后台配置并且在真机上进行调试
    - share:转发当前小程序到微信朋友,但是无法转发到朋友圈
    - getPhoneNumber:获取用户的手机号码信息,如果不是企业小程序是没有权限获取的,
      结合事件bindgetphonenumber来使用,获取到的用户信息可以在回调函数中通过参数拿到(信息已加密)
    - getUserInfo:获取用户的个人信息,这个使用和获取手机号类似,并且不要求是企业小程序,信息未被加密
    - launchApp:在小程序中打开app,前提是先在app中某个链接打开小程序,然后才能在小程序内打开app
    - openSetting:打开小程序内置的授权页面,只会出现用户点击过的权限
    - feedback:打开小程序内置的反馈页面
-->
<button open-type="contact">contact</button>
<button open-type="share">share</button>
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">getPhoneNumber</button>
<button open-type="getUserInfo" bindgetuserinfo="getUserInfo">getUserInfo</button>
<button open-type="launchApp">launchApp</button>
<button open-type="openSetting">openSetting</button>
<button open-type="feedback">feedback</button>

7.8 icon

<!--
  小程序的字体图标:
  type:图标的类型
        success, success_no_circle, info, warn, waiting, cancel, download, search, clear
  size:大小,默认为23,数值越大,图标越大
  color:图标的颜色
-->
<icon type="success" size="23" color="#0094ff" /> 
<icon type="cancel" size="60" color="red" /> 

7.9 radio

<!--
  1 radio单选框必须要搭配父元素radio-group一起使用
  2 value是选中时的值
  3 bindchange是绑定单选框改变事件
  4 color设置选中时的颜色
-->
<radio-group bindchange="handleChange">
  <radio value="male" color="red">男</radio>
  <radio value="female" color="blue">女</radio>
</radio-group>
<view>{{gender}}</view>
Page({

  /**
   * 页面的初始数据
   */
  data: {
    gender: ''
  },
  //处理change事件
  handleChange(e){
    //获取选择的单选框的值
    let gender = e.detail.value
    //赋值给gender
    this.setData({
      //gender: gender
      gender
    })
  }
})

7.10 checkbox

小程序的复选框checkbox同样需要配合父元素checkbox-group一起使用

<view>
  <checkbox-group  bindchange="handleChange">
    <checkbox wx:for="{{list}}" wx:key="id" value="{{item.value}}" color="red">{{item.name}}</checkbox>
  </checkbox-group>
</view>
<view>{{checkedList}}</view>
Page({

  /**
   * 页面的初始数据
   */
  data: {
    list: [
      {
        id: 0,
        name: '苹果',
        value:  'apple'
      },
      {
        id: 1,
        name: '香蕉',
        value:  'banana'
      },
      {
        id: 2,
        name: '鸭梨',
        value:  'yali'
      }
    ],
    checkedList:  []
  },
  //处理change
  handleChange(e){
    //获取选择的值
    const checkedList = e.detail.value;
    //赋值
    this.setData({
      checkedList
    })
  }
})

8、自定义组件

前面所讲都是小程序给我们定义好的组件,在实际开发的时候,会出现两个页面代码十分相似的情况,这个时候我们就可以将这段代码抽取为一个组件。需求:我们肯定在很多app上见过导航栏,当我们点击导航栏上不同项时下方会显示不同的内容,我们接下来就要去做一个这样的自定义组件.

8.1 创建自定义组件

首先,我们在项目下创建一个components文件夹,用于存放组件,然后在该目录下创建Tabs文件夹,文件夹名称一般是要创建的自定义组件的名称,然后在该目录上右键选择创建组件,名字是Tabs,这个创建工作需要在微信开发者工具内进行,然后,我们就可以看到Tabs下出现了类似页面的jswxsswxmljson文件。

"D:\images\学习截图\创建自定义组件.png"

我们打开Tabs.js文件,会发现和页面的有所不同,里面不是Page而是Component:

Component({
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {

  }
})

接下来,我们如何在页面中使用这个自定义组件呢?我们打开某个页面的json文件:

{
  "usingComponents": {
    //左边是组件名,右边是组件的相对路径
    "Tabs":"../../components/Tabs/Tabs"
  }
}

而后,我们打开wxml,在里面使用自定义组件:

<Tabs></Tabs>

8.2 组件优化

首先,我们先在组件的js文件中定义导航栏上的列表项数组:

  data: {
    tabs: [
      {
        id:"0",
        name: '首页',
        isActive: true
      },
      {
        id: "1",
        name: '分类',
        isActive: false
      },
      {
        id: "2",
        name: '联系',
        isActive: false
      },
      {
        id: "3",
        name: '关于',
        isActive: false
      }
    ]
  }

接着在wxml上搭建基本的结构:

<view class="tabs">
  <view class="title">
    <view 
      wx:for="{{tabs}}"
      wx:key="id"
      class="title-item {{item.isActive ? 'active' : ''}}"
      >
      {{item.name}}
    </view>
  </view>
  <view class="content"></view>
</view>

上述中涉及的样式如下:

.tabs{

}
.title{
  display: flex;
  padding: 10rpx;
}
.title-item{
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}
.active{
  color: red;
  border-bottom: 10rpx solid currentColor;
}
.content{

}

打开微信开发者工具预览一下:
"D:\images\学习截图\自定义组件基本结构.png"

8.3 添加激活选中

接下来,我们需要,给item项添加激活选中。首先,我们给所有item添加一个自定义属性,值是循环项的索引,并绑定tap事件:

<view 
      wx:for="{{tabs}}"
      wx:key="id"
      class="title-item {{item.isActive ? 'active' : ''}}"
      bindtap="handleTap"
      data-index="{{index}}"
      >
      {{item.name}}
    </view>

接下来,我们需要在js文件中定义一个handleTap方法,注意:组件的方法不是和data同级的,而是需要放在methods里面:

handleTap(e){
      //1 获取点击的item的索引
      //等价于=》const index = e.currentTarget.dataset.index
      const {index} = e.currentTarget.dataset;
      //2 获取遍历的数组
      //等价于=》const tabs = this.data.tabs
      const {tabs} = this.data;
      //3 遍历数组,将点击项设为激活状态,其它都是非激活状态
      tabs.forEach((v,i) => i === index ? v.isActive = true : v.isActive = false)
      this.setData({
        tabs
      })
    }

8.4 父组件向子组件传递数据

首先,父组件(页面)是通过标签属性的方式向子组件传递数据的。我们先将自定义组件的item项列表移动到使用父组件的页面的js文件的data中:

  /**
   * 页面的初始数据
   */
  data: {
    tabs: [
      {
        id: "0",
        name: '首页',
        isActive: true
      },
      {
        id: "1",
        name: '分类',
        isActive: false
      },
      {
        id: "2",
        name: '联系',
        isActive: false
      },
      {
        id: "3",
        name: '关于',
        isActive: false
      }
    ]
  }

接着,我们在该页面的wxml中通过标签属性的方式传递给子组件:

<!--
  父组件(页面)向子组件传递数据通过标签属性的方式传递
-->
<Tabs tabs="{{tabs}}"></Tabs>

接着,我们需要在子组件也就是自定义组件的js文件的properties中通过这个tabs属性去接收父组件的数据:

properties: {
    tabs:{
      //type表示属性的类型
      type:Array,
      //value默认值
      value:[]
    }
  }

我们可以和使用data里面的数据一样使用properties内的数据:

 <view class="title">
    <view 
      wx:for="{{tabs}}"
      wx:key="id"
      class="title-item {{item.isActive ? 'active' : ''}}"
      bindtap="handleTap"
      data-index="{{index}}"
      >
      {{item.name}}
    </view>
  </view>

8.5 子组件向父组件传递数据

子组件向父组件传递数据一般通过自定义事件的方式传递。我们在handleTap里面获取点击的item的索引,并将其传递给父组件:

handleTap(e){
      //1 获取索引
      const {index} = e.currentTarget.dataset;
      //2 通过自定义事件传递给父组件
      //itemChange是自定义事件的名称,第二参数是我们要传递的数据,这里使用了简写,等价于{index:index}
      this.triggerEvent("itemChange",{index});
    }

接着,我们需要在使用子组件的地方使用bind+自定义事件名来接收子组件传递的数据:

<Tabs tabs="{{tabs}}" binditemChange="handleItemChange"></Tabs>
//处理itemChange
  handleItemChange(e){
    //拿到子组件传递的index
    const {index} = e.detail;
    //获取数组
    const {tabs} = this.data;
    //遍历数组
    tabs.forEach((v,i) => i === index ? v.isActive = true : v.isActive = false)

    this.setData({
      tabs
    })
  }

8.6 slot

slot是插槽的意思,它实际上是一个占位符,当我们的父组件调用子组件时,会传递内容来替换这个占位符。首先我们在子组件内加入插槽:

<view class="content">
    <!--
      slot是插槽的意思,它其实就是一个占位符,
      当父组件调用子组件的时候,可以传递内容过来
      将其替换
    -->
    <slot></slot>
  </view>

接着,在使用子组件的内部加入要替换插槽的内容:

<Tabs tabs="{{tabs}}" binditemChange="handleItemChange">
  <block wx:if="{{tabs[0].isActive}}">0</block>
  <block wx:elif="{{tabs[1].isActive}}">1</block>
  <block wx:elif="{{tabs[2].isActive}}">2</block>
  <block wx:else="{{tabs[3].isActive}}">3</block>
</Tabs>

9、小程序的生命周期

小程序的生命周期分为应用的生命周期页面的生命周期

9.1 应用的生命周期

应用的生命周期,我们需要通过app.js来了解:

App({
  //小程序第一次启动触发的事件
  onLaunch(){
    console.log("onLaunch");
    // aaxasxa
  },
  //小程序页面出现在用户面前的时候触发的事件,比如说:
  //我先切换到其它应用,然后这个时候再切回来,这个时候就会执行这个方法
  onShow(){
    console.log("onShow");
  },
  //小程序页面隐藏的时候,和onShow相对
  onHide(){
    console.log("onHide");
  },
  //小程序出现代码错误的时候触发
  onError(err){
    console.log("onError");
  },
  //小程序页面找不到时触发,只会在应用第一次启动时触发
  onPageNotFound(){
    console.log("onPageNotFound");
  }
})

9.2 页面的生命周期

页面的生命周期函数在xxx.js中使用:

Page({

  /**
   * 页面的初始数据
   */
  data: {

  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    console.log("onLoad");
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    console.log("onReady");
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    console.log("onShow");
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
    console.log("onHide");
  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
    //页面卸载指的是当前页面被关闭(无法回退到该页面)
    console.log("onUnload");
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
    //一般用于刷新当前页面的数据
    console.log("onPullDownRefresh");
  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    //一般用于加载下一页的数据
    console.log("onReachBottom");
  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
    console.log("onShareAppMessage");
  },
  /**
   * 页面发生滚动时触发
   */
  onPageScroll: function (){
    console.log("onPageScroll");
  },
  /**
   * 页面尺寸发生变化时触发,手机上一般指的是横屏和竖屏之间的切换
   */
  onResize: function(){
    console.log("onResize");
  },
  /**
   * 当前页是tab页时点击tab触发
   */
  onTabItemTap: function(){
    console.log("onTabItemTap");
  }
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值