微信小程序开发常用知识

生命周期

应用的生命周期函数

onLaunch(Object object)
小程序初始化完成时触发,全局只触发一次。参数也可以使用 wx.getLaunchOptionsSync 获取。
onShow(Object object)
小程序启动,或从后台进入前台显示时触发。也可以使用 wx.onAppShow 绑定监听。
onHide()
小程序从前台进入后台时触发。也可以使用 wx.onAppHide 绑定监听。
onError(String error)
小程序发生脚本错误或 API 调用报错时触发。也可以使用 wx.onError 绑定监听

页面的生命周期函数

onLoad(Object query)
页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
onReady()
页面初次渲染完成时触发。一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。
注意:对界面内容进行设置的 API 如wx.setNavigationBarTitle,请在onReady之后进行。
onHide()
页面隐藏/切入后台时触发。 如 wx.navigateTo 或底部 tab 切换到其他页面,小程序切入后台等。
onUnload()
页面卸载时触发。如wx.redirectTo或wx.navigateBack到其他页面时。

WXS脚本

内联的wxs脚本

wxs 代码可以编写在 wxml 文件中的 < wxs > 标签内,就像 Javascript 代码可以编写在 html 文件中的 < script >标签内一样。wxml文件中的每个< wxs >< /wxs >标签,必须提供module属性,用来指定当前wxs的模块名称,方便在wxml 中访问模块中的成员

<view>{{m1.toUpper(username)}}</view>
<wxs module="m1">
  module.exports.toUpper=function(str){
    return str.toUpperCase()
  }
</wxs>

外联的wxs脚本

//utils/tools.wxs
function toLower(str){
  return str.toLowerCase()
}

module.exports={
  toLower:toLower
}

在 wxml 中引入外联的 wxs 脚本时,必须为 标签添加 module 和 src 属性,其中:
module 用来指定模块的名称
src 用来指定要引入的脚本的路径,且必须是相对路径

<view>{{m1.toLower(username)}}</view>
<wxs src="../../utils/tools.wxs" module="m1"></wxs>

自定义组件之数据监听器

需求:点击R G B改变view颜色

<!--components/test/test.wxml-->
<view style="background-color:rgb({{fullColor}});" class="colorBox">颜色值:			    {{fullColor}}</view>
	<button size="mini" type="default" bindtap="changeR">R</button>
	<button size="mini" type="primary" bindtap="changeG">G</button>
	<button size="mini" type="warn" bindtap="changeB">B</button>
<!-- <view>{{rgb.r}},{{rgb.g}},{{rgb.b}}</view> -->


// components/test/test.js
Component({
  options:{
    //指定_开头的为纯数据字段
    pureDataPattern:/^_/
  },
  properties: {

  },
  data: {
    _rgb:{
      r:0,
      g:0,
      b:0
    },
    fullColor:'0, 0, 0'
  },
  observers:{
    '_rgb.r,_rgb.g,_rgb.b':function(r,g,b){
      this.setData({
        fullColor:`${r}, ${g}, ${b}`
      })
    }
    // '-_rgb.**':function(obj){
    //   this.setData({
    //     fullColor:`${obj.r}, ${obj.g}, ${obj.b}`
    //   })
    // }
  },
  methods: {
    changeR() {
      this.setData({
        '_rgb.r': this.data._rgb.r + 5 > 255 ? 255 : this.data._rgb.r + 5
      })
    },
    changeG() {
      this.setData({
        '_rgb.g': this.data._rgb.g + 5 > 255 ? 255 : this.data._rgb.g + 5
      })
    },
    changeB() {
      this.setData({
        '_rgb.b': this.data._rgb.b  + 5 > 255 ? 255 : this.data._rgb.b + 5
      })
    },
    _randomColor(){
      this.setData({
        _rgb:{
          r: Math.floor(Math.random()*256),
          g: Math.floor(Math.random()*256),
          b: Math.floor(Math.random()*256)
        }
      })
    }
  },
  lifetimes:{
    created(){console.log('created');},
    attached(){console.log('attached');}
  },
  pageLifetimes:{
    show(){
      console.log('show');
      this._randomColor()
    },
    hide(){console.log('hide');},
    resize(){console.log('resize');},
  }
})

app.json中全局引用

  "usingComponents": {
    "my-test":"/components/test/test"
  }

自定义组件之父子组件通信

父组件

<my-test1 count="{{count}}" bind:sync="syncCount" class="customA"></my-test1>
<view>父组件中,count值是{{count}}</view>
<button bindtap="getChild">获取子组件实例对象</button>

Page({
  data: {
    count:0
  },
  syncCount(e){
    this.setData({
      count:e.detail.value
    })
  },
  getChild(){
    const child = this.selectComponent('.customA')
    // console.log(child);
    // child.setData({
    //   count:child.properties.count + 1
    // })
    child.addCount()
  }
})

子组件

<!--components/test1/test1.wxml-->
<view>子组件中,count值是{{count}}</view>
<button bindtap="addCount">+1</button>

// components/test1/test1.js
Component({
  properties: {
    count: Number
  },
  data: {
  },
  methods: {
    addCount(){
      this.setData({
        count: this.data.count + 1
      })
      this.triggerEvent('sync',{value:this.properties.count})
    }
  }
})

自定义组件

全局引用组件
在app.json中配置引用组件

{
  "usingComponents": {
    "my-test":"/components/test/test"
  }
}

自定义组件的样式

//表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将:将不会相互影响
Component({
  options:{
    styleIsolation:'isolated'
  }
})

自定义组件传递参数

Component({
  properties: {
    count:{           //完整定义方式
      type:Number,  //属性值数据类型
      value:10      //属性默认值
    },
    count:Number      //简化定义方式
  },
})

<my-test count="10"></mt-test>

数据监听器

Component({
  observers:{
    '字段A,字段B':function(字段A的新值,字段B的新值){
      //do something
    }
  }
})

lifetimes节点:

Component({
  lifetimes:{
    created(){
      console.log('created');
    },
    attached(){
      console.log('attached');
    }
  }
})

插槽

在自定义组件的 wxml 结构中,可节点(插槽),用于承载组件使用者提供的wxml结构

//组件
<view>
  <view>这里是组件的内部结构</view>
  <slot></slot>
</view>

//页面
<my-test1>
  <view>这是通过插槽填充ode内容</view>
</my-test1>

启用多个插槽

启用多个插槽

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

//页面
<my-test1>
  <view slot="before">AAA</view>
  <view slot="after">BBB</view>
</my-test1>

//组件
<view>
  <slot name="before"></slot>
  <view>这里是组件的内部结构</view>
  <slot name="after"></slot>
</view>

父子组件之间的通信

//父组件自定义事件
syncCount(e){
  this.setData({
    count:e.detail.value
  })
},

//父组件绑定事件
<my-test1 count="{{count}}" bind:sync="syncCount" class="customA"></my-test1>

//子组件触发事件
methods: {
  addCount(){
    this.setData({
      count: this.data.count + 1
    })
    this.triggerEvent('sync',{value:this.properties.count})
  }
}

获取组件实例

  getChild(){
    const child = this.selectComponent('.customA')
    // console.log(child);
    // child.setData({
    //   count:child.properties.count + 1
    // })
    child.addCount()
  },

behaviors

behaviors 是小程序中,用于实现组件间代码共享的特性,类似于Vue.js中的“mixins"。
每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中。
每个组件可以引用多个behavior, behavior 也可以引用其他behavior。

// 调用 Behavior()方法,创建实例对象
// 并使用module.exports将behavior实例对象共享出去
module.exports = Behavior({
	// 属性节点
	properties:{},
	// 私有数据节点
	data:{ username: 'zs'},
	// 事件处理函数和自定义方法节点
	methods:{},
	// 其它节点..
})

// 1.使用 require()导入需要的自定义benavior模块
const myBehavior = require("../../behaviors/my-behavior)
Component({
// 2.将导入的 behavior 实例对象,挂载到 behaviors 数组节点中,即可生效
behaviors: [myBehavior],
// 组件的其它节点...
})

Vant Weapp

npm init -y
npm i @vant/weapp -S --production

实现API promise化

npm install --save miniprogram-api-promise@1.0.4

//app.js
import { promisifyAll } from 'miniprogram-api-promise'
const wxp = wx.p = {}
promisifyAll(wx,wxp)

//.wxml
<van-button type="primary" bindtap="getInfo">主要按钮</van-button>

//.js
async getIngo(){
  const {data: res} = await wx.p.request({
    method: 'GET',
    url: '',
    data: {name:'zs',age:20}
  })
  console.log(res)
},

全局数据共享

全局数据共享(又叫做:状态管理)是为了解决组件之间数据共享的问题。
开发中常用的全局数据共享方案有:Vuex、Redux、MobX等。
在小程序中,可使用 mobx-miniprogram配合mobx-miniprogram-bindings实现全局数据共享。其中:
mobx-miniprogram 用来创建 Store 实例对象
mobx-miniprogram-bindings 用来把 Store 中的共享数据或方法,绑定到组件或页面中使用

npm i --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1

store.js

//用来创建Store的实例对象
import {action, observable} from 'mobx-miniprogram'

export const store = observable({
  //数据字段
  numA:1,
  numB:2,
  //计算属性,get表示只读
  get sum(){
    return this.numA+this.numB
  },
  //action方法,用来修改store中的值
  updateNumA:action(function(step){
    this.numA+=step
  }),
  updateNumB:action(function(step){
    this.numB+=step
  }),
  }
)

将store中的成员绑定到页面中

import {createStoreBindings} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store'
Page({
  onLoad: function (options) {
    this.storeBindings=createStoreBindings(this,{
      store,
      fields:['numA','numB','sum'],
      actions:['updateNumA']
    })
  },
  onUnload: function () {
    this.storeBindings.destroyStoreBindings()
  },
  btnHandler(e){
    this.updateNumA(e.target.dataset.step)
  },
})

在页面中使用store中的成员

<view>{{numA}}+{{numB}}={{sum}}</view>
<van-button type="primary" bindtap="btnHandler" data-step="{{1}}">numA + 1</van-button>
<van-button type="danger" bindtap="btnHandler" data-step="{{-1}}">numA - 1</van-button>

将store中的成员绑定到组件中

import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store'
Component({
  behaviors:[storeBindingsBehavior],
  storeBindings:{
    store,
    fields:{
      numA:'numA',
      numB:'numB',
      sum:'sum'
    },
    actions:{
      updateNumB:'updateNumB'
    }
  },
  methods: {
    btnHandler2(e){
      this.updateNumB(e.target.dataset.step)
    }
  }
})

在组件中使用store中的成员

<view>{{numA}}+{{numB}}={{sum}}</view>
<van-button type="primary" bindtap="btnHandler2" data-step="{{1}}">numB + 1</van-button>
<van-button type="danger" bindtap="btnHandler2" data-step="{{-1}}">numB - 1</van-button>

分包

普通分包

//app.json
{
  "pages":[ // 主包的所有页面
    "pages/index",
    "pages/logs"
  ],
  "subpackages"[ // 通过 subpackages节点,声明分包的结构
    {
      "root""packageA"// 第一个分包的根目录
      "pages"[ // 当前分包下,所有页面的相对存放路径
        "pages/cat"
        "pages/dog"
    },{
      "root""packageB"// 第二个分包的根目录
      "name": "pack2",// 分包的别名
      "pages"[ // 当前分包下,所有页面的相对存放路径
        "pages/apple",
        "pages/banana"
      ]
    }
  ]
}

打包原则:
小程序会按 subpackages 的配置进行分包,subpackages 之外的目录将被打包到主包中
主包也可以有自己的 pages(即最外层的 pages字段)
tabBar 页面必须在主包内
分包之间不能互相嵌套

引用原则:
主包无法引用分包内的私有资源
分包之间不能相互引用私有资源
分包可以引用主包内的公共资源

独立分包

开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中。原因如下:
当小程序从普通的分包页面启动时,需要首先下载主包,而独立分包不依赖主包即可运行,
,可以很大程度上提升分包页面的启动速度
添加"independent":true节点

//app.json
{
  "pages":[ // 主包的所有页面
    "pages/index",
    "pages/logs"
  ],
  "subpackages"[ // 通过 subpackages节点,声明分包的结构
    {
      "root""packageA"// 第一个分包的根目录
      "pages"[ // 当前分包下,所有页面的相对存放路径
        "pages/cat"
        "pages/dog"
    },{
      "root""packageB"// 第二个分包的根目录
      "name": "pack2",// 分包的别名
      "pages"[ // 当前分包下,所有页面的相对存放路径
        "pages/apple",
        "pages/banana"
      ],
      "independent":true
    }
  ]
}

独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源!例如:
1.主包无法引用独立分包内的私有资源
2.独立分包之间,不能相互引用私有资源
3.独立分包和普通分包之间,不能相互引用私有资源
4.特别注意:独立分包中不能引用主包内的公共资源

分包预下载

{
  "preloadRule":{ // 分包顶下载的规则
    "pages/contact/contact":{ // 触发分包预下载的贝面路径
      // network 表示在指定的网络模式下进行预下载,
      // 可选值为:all(不限网络)和 wifi(仅 wifi 模式下进行预下载)
      // 默认值为:wifi
      "network":"all",
      // packages 表示进入页面后,预下载哪些分包
      // 可以通过 root 或 name 指定预下载哪些分包
      "packages":["pkgA"]
    }
  }
}

自定义tabbar

//app.json
  "tabBar":{
    "custom":true,
    "list":[...]//保留list,保证版本兼容
  }

创建custom-tab-bar
在这里插入图片描述

<!--custom-tab-bar/index.wxml-->
<van-tabbar active="{{ active }}" bind:change="onChange" active-color="#13A7A0">
  <van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info ? item.info:''}}">
    <image
      slot="icon"
      src="{{item.iconPath}}"
      mode="aspectFit"
      style="width: 25px; height: 25px;"
    />
    <image
      slot="icon-active"
      src="{{item.selectedIconPath}}"
      mode="aspectFit"
      style="width: 25px; height: 25px;"
    />
    {{item.text}}
  </van-tabbar-item>
</van-tabbar>

// custom-tab-bar/index.js
import { storeBindingsBehavior } from "mobx-miniprogram-bindings";
import { store } from "../store/store";
Component({
  behaviors: [storeBindingsBehavior],
  /**
   * 组件的属性列表
   */
  options: {
    styleIsolation: 'shared',
  },
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    list: [{
        "pagePath": "/pages/home/home",
        "text": "首页",
        "iconPath": "/images/tabs/home.png",
        "selectedIconPath": "/images/tabs/home-active.png"
      },
      {
        "pagePath": "/pages/message/message",
        "text": "消息",
        "iconPath": "/images/tabs/message.png",
        "selectedIconPath": "/images/tabs/message-active.png",
        "info":2
      },
      {
        "pagePath": "/pages/cart/cart",
        "text": "购物车",
        "iconPath": "/images/tabs/cart.png",
        "selectedIconPath": "/images/tabs/cart-active.png"
      },
      {
        "pagePath": "/pages/contact/contact",
        "text": "联系我们",
        "iconPath": "/images/tabs/contact.png",
        "selectedIconPath": "/images/tabs/contact-active.png"
      }
    ]
  },
  
  storeBindings: {
    store,
    fields: {
      numA: () => store.numA,
      numB: (store) => store.numB,
      sum: "sum",
      active:'activeTabBarIndex'
    },
    actions: {
      buttonTap: "update",
      updateActive:'updateActiveTabBarIndex'
    },
  },
  observers:{
    'sum':function(val){
      console.log(val)
      this.setData({
        'list[1].info':val
      })
    }
  },
  /**
   * 组件的方法列表
   */
  methods: {
    onChange(event) {
      // event.detail 的值为当前选中项的索引
      // this.setData({
      //   active: event.detail
      // });
      this.updateActive(event.detail)
      wx.switchTab({
        url: this.data.list[event.detail].pagePath
      })
    },
    myMethod() {
      this.data.sum; // 来自于 MobX store 的字段
    }
  }
})
//store.js
//在这个JS文件中,专门来创建 Store 的实例对象

import { observable,action } from "mobx-miniprogram"

export const store = observable({
  //数据字段
  numA:1,
  numB:2,
  activeTabBarIndex:0,
  //计算属性
  get sum(){
    return this.numA + this.numB
  },
  //actions方法,用来修改store中的数据
  updateNum1:action(function(step){
    this.numA +=step
  }),
  updateNum2:action(function(step){
    this.numB +=step
  }),
  updateActiveTabBarIndex:action(function(index){
    this.activeTabBarIndex=index
  })
})

导入vsCode中的插件 使用Easy LESS插件将.less 文件转换为.wxss
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

小程序中的模板引入

先看实现效果
在这里插入图片描述
在这里插入图片描述

<template name="mytitle">
  <view class="mytitle">
    <view class="line"></view>
    <view class="txt">{{content}}</view>
  </view>
</template>
//引入使用
<import src="./templates/Title.wxml" />
<view class="about">
    <template is="mytitle" data="{{content: '相关产品'}}"></template>
</view>
/*样式*/
 .mytitle{
    height: 80rpx;
    background: #fff;
    position: relative;
    .line{
      width: 50%;
      height: 4rpx;
      background: #ccc;
      position: absolute;
      left: 0;top: 0;right: 0;bottom: 0;
      margin: auto;
    }
    .txt{
      width: 36%;
      height: 80rpx;
      line-height: 80rpx;
      text-align: center;
      font-size: 36rpx;
      background: #fff;
      position: absolute;
      left: 0;top: 0;right: 0;bottom: 0;
      margin: auto;
    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值