一 、注册事件
// 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()