微信小程序小笔记

513 阅读7分钟

一 、注册事件

//  bindtap --- 点击事件

//  使用click会有 200 - 300ms 延迟  (解决办法)
// 1. fastclick(插件)  2. 不使用click 使用 tap  zepto(类似jq) 3. touchstart

// 原生js 直接使用 onmousedown + onmouseup
// 在js中调用msg,要使用this.data,msg
// 修改data中的数据必须是setData,只有setData才会触发视图的更新

二、双向数据绑定

// bindinput 绑定input
<input type="text" style="border: 2rpx solid  #000;" value="{{text}}" bindinput="inputFn" />
<text>{{text}}</text>

data:{  text:'双向数据绑定' }

inputFn(e){
	this.setData({
		text:e.detaol.val
	})
}

三、 循环生成数据

// block 空标签 可以在外面包裹 b
wx:for -- 绑定   wx:ket='*this' -- 提升性能
<view wx:for="{{arr}}" wx:key="*this">{{index}}----{{item}}</view>
// index item 封装好了的 
data:{
	arr:['刘备','关羽','张飞'],
    myarr:[
        {class:1,students:['貂蝉','火舞','小乔']},
        {class:2,students:['貂蝉1','火舞1','小乔1']},
        {class:3,students:['貂蝉2','火舞2','小乔2']},]
}
//------------------------------------
<view wx:for="{{myarr}}" wx:key="*this">
    							// 重新命名 wx:for-item="el"  便于解读
    <text wx:for="{{item.students}}" wx:key="*this" wx:for-item="el">{{el}}</text>
   	<text>是{{item.class}}班的 </text>
</view>

//  wx:key的值:
//  1.index 2.任意字段(每一项中的属性) 3.*this代表拿当前数组项做key

// 拿到 data里面的数据
// this.data.arr

四 、显示与隐藏

//  wx:if --  操作DOM的显示隐藏  false/true -- 显示/隐藏  销毁
data:{ flag: false}
// hidden   false/true  --  隐藏/显示   (反向判断)   display = none/block

// wx:if 条件判断
data:{
	score :90
}
<view wx:if = "{{score >= 90}}">优秀</view>
<view wx:elif = "{{score >= 60}}">及格</view>
<view wx:else>不及格</view>

五 、WXS模块的使用

// 在 wxml 文件中的 <wxs> 标签内
<view>{{tools.filterPrice(price)}}</view> // 99.00元
data:{price:99}
<wxs module="tools">  
// wxs 中只支持Es5 不支持Es6
    function filterPrice(val){
        return "¥" + val.toFixed(2) + '元'
    }
    // 导出
    module.exports = {
        filterPrice:filterPrice
    }
</wxs>
// 以 .wxs 为后缀名的文件内。
// 写好wxs文件 然后使用 module.exports 导出要使用的方法或变量
// 在待使用页面 使用 <wxs src="/path" module="tools" /> 引入
// 在插值{{}}中使用 tools.method_name(para)

六、 模板的使用

//在 pages/home/ 目录下创建 templates 文件夹,里面用于存放模板文件。我们新建 item.wxml 
template name="box1">
  <text bindtap="txtFn">box1: {{content}}</text>
</template>

<import src="./templates/item.wxml" /> 页面内引入        
<template is="box1" data="{{content: txt}}"></template>

// 创建模板时,我们写的 bindtap="txtFn" ,实现txtFn的方法,需要写在 调用方 的js文件中,而非模板的js文件。
// home.js
Page({
  data: {
    txt: '穿越火线'
  },
  // 可供模板调用的方法
  txtFn(){
    console.log('打印...')
  }
})

七、组件化开发

1、创建组件

// 可以在 app.json 中的pages进行创建:
{
  "pages": [
    ...,
    "components/product/product"
  ],
}

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

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

// 注意注意:这里的Page()方法改成了Component()方法
Component({
  data: {
    showArr: [
      {imgSrc: "/images/home/newPro1.jpg", imgTxt: "卡布奇诺"},
      {imgSrc: "/images/home/newPro2.jpg", imgTxt: "黑咖啡"},
    ]
  },
})

3、声明为组件

// 在 product.json 中:
{
  "usingComponents": {},
  "component": true
}

4、调用组件

在 home.json 中:
{
  "usingComponents": {
    "product-block": "/components/product/product"
  },
  "navigationStyle": "custom" // 自定义
}
在 home.wxml 中:
<product-block />
或:
<product-block></product-block>

八、组件传值

1、父传子

// 借用上面的例子,将数据放到Home.js中的data里
// 子组件
<product-block showArr="{{showArr}}" />
 // product.js 中:
 Component({
  // properties用于接收传值,类似于vue中的props
  properties: {
    SongArr: {
      // 设置数据类型
      type: Array,
 			// 设定初始值(即默认值)
      value: [{imgSrc: "/images/home/newPro1.jpg", imgTxt: "卡布奇诺"}]
       // 或 根据数据类型判断 数组为
       value:[]
    }
  }
})
// 渲染
<view class="product_list">
  <view wx:for="{{SongArr}}" wx:key="*this" class="product_list_box">
    <view>{{item.imgTxt}}</view>
	<image src="{{item.imgSrc}}" mode="widthFix"></image>
  </view>
</view>

2、子传父

//  点击 product 组件中的任意一项,来触发父级的事件。
// 子组件
<view class="product_list">
  <view wx:for="{{showArr}}" wx:key="*this" class="product_list_box" bindtap="productTap">
    ...
  </view>
</view>

// components/product/product.js
Component({
  ...,
  // 如果是组件,不是页面,就必须写methods
  methods: {
    productTap(){
  		// 小程序中子传父通过triggerEvent来实现
      this.triggerEvent('fatherEvent', 100);
    }
  }
})
<!-- 标签上使用bind来接收子组件传过来的事件 -->
<product-block  bind:fatherEvent="事件名" />
Page({
  ...,
  // 页面无需写methods
  事件名(event){
    console.log(event.detail); // 100
  }
})

3、全局变量globalData

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

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

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

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

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

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

九、路由跳转

1、跳转到非tabbar页面

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)

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

3、跳转到tabbar页面

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

十、生命周期

1、页面的生命周期:

onLoad > onShow > onReady > onHide > onShow > onUnload

2、组件生命周期

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

十一、数据请求

wx.request({
  url: 'http://XXXXXXXXXXXXX.com',
  success(res){
    console.log(res);
  }
})
request.js 是用来封装请求的,一般我们不动它
api.js 是用来统一管理Restful风格的接口地址与baseUrl的
fetch.js 是用来导出请求函数,供页面调用的,其中有3套模板,大家可以直接copy使用

// 数据请求封装  创建request文件夹 和pages同级

//    request/api.js 
//    开发的服务器
var baseUrl = 'http://xxxxxxx'
//    测试的服务器
// var baseUrl = 'http://xxxx'
//    正式环境
// var baseUrl = 'http://xxxx'
//    主页数据请求
var indexApi = baseUrl + '/index/index'
// 	  导出
module.exports = { indexApi }

// request/fetch.js
var api = require('./api.js')
var request = require('./request.js')
// get请求不携带参数
function getHome() {
  return request.requestApi({
    url: api.homeApi
  })
}
// get请求携带参数
function getList(params) {
  return request.requestApi({
    url: api.listApi,
    data: params,
  })
}
// post请求
function LoginFn(params) {
  return request.requestApi({
    url: api.loginApi,
    data: params,
    header: {
      'content-type': 'application/x-www-form-urlencoded'
    },
    method: 'POST'
  })
}
// 主页请求
function indexApi() {
  return request.requestApi({
    url: api.indexApi
  })
}
module.exports = {
  indexApi: indexApi,
}

//  request/request.js
function request(params) {
  // 封装网络请求的代码
  return new Promise(function (resolve, reject) {
    wx.showLoading({
      title: '加载中...',
    })
    wx.request({
      url: params.url,
      data: params.data || {},
      header: params.header || {},
      method: params.method || 'GET',
      dataType: 'json',
      success: function(res) {
        wx.hideLoading()
        resolve(res.data)
      },
      fail: function(err) {
        wx.showToast({
          title: err || '请求错误!',
        })
        reject(err)
      }
    })
  }) 
}
// nodejs common
module.exports = {
  requestApi: request
}

// 页面内引入
const { indexApi } = require("../../request/fetch.js")

十二、Vant Weapp 组件库

vant-contrib.gitee.io/vant-weapp/…

面试题

小程序的this.setData

// 解决setData 性能问题 减少使用
this.setData(obj,callback) 数据更新是同步的 视图更新是异步的

小程序应用的生命周期

onLaunch() 用户首次打开小程序触发(全局只触发一次)
onShow() 小程序初始化完成后触发,小程序从后台进入前台也会触发
onHide() 小程序从前台进入后台触发
onError() 小程序发生脚本错误或者API调用失败时触发

小程序页面的生命周期函数?

onLoad() 页面加载时触发,只会调用一次,可获取当前页面路径中的参数。
onShow() 页面显示/切入前台时触发,一般用来发送数据请求;
onReady() 页面初次渲染完成时触发, 只会调用一次,代表页面已可和视图层进行交互。
onHide() 页面隐藏/切入后台时触发, 如底部 tab 切换到其他页面或小程序切入后台等。
onUnload() 页面卸载时触发,如redirectTo或navigateBack到其他页面时。

简述微信小程序原理

  • 小程序本质就是一个单页面应用,所有的页面渲染和事件处理,都在一个页面内进行,但又可以通过微信客户端调用原生的各种接口;
  • 它的架构,是数据驱动的架构模式,它的UI和数据是分离的,所有的页面更新,都需要通过对数据的更改来实现;
  • 它从技术讲和现有的前端开发差不多,采用JavaScript、WXML、WXSS三种技术进行开发;
  • 功能可分为webview和appService两个部分;
  • webview用来展现UI,appService有来处理业务逻辑、数据及接口调用;
  • 两个部分在两个进程中运行,通过系统层JSBridge实现通信,实现UI的渲染、事件的处理等

小程序的路由方式

**打开新页面:**调用 API wx.navigateTo

**页面重定向:**调用 API wx.redirectTo

**页面返回:**调用 API wx.navigateBack

**Tab 切换:**调用 API wx.switchTab

**重启动:**调用 API wx.reLaunch

数据缓存

//  新增-缓存变量username为"小陈"
//  wx.setStorageSync(string key, any data)
wx.setStorageSync('username', '小陈')
//  查找-缓存变量username
any wx.getStorageSync(string key)
const name = wx.getStorageSync('username')
//  修改-缓存变量username 
// wx.setStorageSync(string key, any data)
wx.setStorageSync('username', '陈大哥')
//  删除缓存变量username
// wx.removeStorage(Object object)
wx.removeStorageSync('username')
//  清空所有缓存变量
//  wx.clearStorage(Object object)
wx.clearStorageSync()