前端前端小程序微信原生小程序学习笔记
Juns小程序笔记
跨平台框架
- uni-app
- 使用 Vue 开发,可以发布到多端,ios,安卓,web,各种小程序
- taro
- 支持 React/Vue/Nerv 等框架
- 更加灵活
小程序的配置和架构
双线程模型
web-view 和 jsCore,渲染层和逻辑层
- WXML 和 WXSS 运行于渲染层,使用 WebView 渲染
- JS 运行于逻辑层,使用 JsCore 运行
- 两个线程都会经由微信客户端进行中转交互
生命周期
面试官:说说微信小程序的生命周期函数有哪些? | web 前端面试 - 面试官系列 (vue3js.cn)
生命周期 | 微信开放文档 (qq.com)
双线程
App.js
获取进入小程序的方式
场景值
场景值列表
在 onLaunch 和 onShow 生命周期回调函数中,有 options 参数,其中有 scene 值,可以用于判断
onShow(options) { console.log("onShow"); console.log(options); console.log(options.scene); }
|
定义全局数据
globalData: { token: "11111", userInfo: { avatarUrl: "avatarUrl", city: "city", country: "country", }, },
|
使用:
onLoad() { const app = getApp(); const token = app.globalData.token; const userInfo = app.globalData.userInfo; console.log(token, userInfo); this.setData({ userInfo }); },
|
初始化操作
- 登录操作
- 读取本地数据,如 token
- 请求所需数据
const token = wx.getStorageSync('token') const userInfo = wx.getStorageSync('userInfo') console.log('Storage:', token, userInfo) if (!token || !userInfo) { wx.setStorageSync('token', 'token in storage') wx.setStorageSync('userInfo', { nickname: 'juns', level: 100 }) }
this.globalData.token = token this.globalData.userInfo = userInfo
|
Page 函数
注册时一般要做的
- 在生命周期函数中发送网络请求
- 初始化数据
- 监听事件绑定
常见组件等
获取用户信息
getUserInfo() { wx.getUserProfile({ desc: "test", }).then((res) => { console.log(res.userInfo); }); },
|
获取用户手机号,不对个人开发者开放
<t-button theme="light" size="large" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber" > 获取手机号 </t-button>
|
getPhoneNumber(e) { console.log(e); },
|
图片常用属性,占满给的宽度(默认 w320,h240),高度会自动计算
<image src="...." mode="widthFix" />
|
展示用户本地图片
<view class="container"> <view class="imgContainer"> <image src="{{chooseImgUrl}}" mode="widthFix" ></image> </view> <t-button bindtap="chooseImg">选择图片</t-button> </view>
|
Page({ data: { chooseImgUrl: '', }, chooseImg() { wx.chooseMedia({ mediaType: 'image', }).then(res => { console.log(res) const url = res.tempFiles[0].tempFilePath this.setData({ chooseImgUrl: url }) }) }, })
|
数据双向绑定
<input class="input1" placeholder="请输入文字" model:value="{{inputVal}}" /> <text>{{inputVal}}</text>
|
WXSS 尺寸单位
rpx(responsive pixel):可以根据屏幕宽度自适应,规定屏幕宽度是 750rpx
iPhone6 中:1px===2rpx
WXML 语法
WXS
小程序的脚本语言,在 WXML 中不能直接调用 Page 里面的函数,所以用 WXS 来解决
在 WXML 内写法:
<wxs module="format"> function formatPrice(price){ return "¥"+price; } module.exports={ formatPrice:formatPrice } </wxs> <view class="container"> <block wx:for="{{list}}" wx:key="*this" > <view>{{format.formatPrice(item)}}</view> </block> </view>
|
引入写法
function formatPrice(price) { return '¥' + price } module.exports = { formatPrice: formatPrice, }
|
<wxs module="format" src="/utils/format.wxs" ></wxs>
<view class="container"> <block wx:for="{{list}}" wx:key="*this" > <view>{{format.formatPrice(item)}}</view> </block> </view>
|
事件处理
参数传递
data-name="why"
,然后 js 里面用 event 传递,event.target.dataset
mark 也可以传递数据,会向上冒泡合并,上面的需要是 currentTarge
<view mark:name="nael"> </view>
|
组件化开发
样式
通信
数据 properties
使用的页面<section-info title="www" desc="哇哦哇哦" />
Component({ properties: { title: { value: '默认标题', type: String, }, desc: { value: '默认描述', type: String, }, }, })
|
样式 externalClasses
组件 wxml
<view class="container"> <h1>{{title}}</h1> <h3 class="info">{{desc}}</h3> </view>
|
组件 js
Component({ properties: { title: { value: '默认标题', type: String, }, desc: { value: '默认描述', type: String, }, }, externalClasses: ['info'], })
|
页面 wxml<section-info title="www" desc="哇哦哇哦" info="test" />
页面 css
.test { background-color: slateblue; }
|
插槽
slot
,但是小程序不支持默认值
<view class="container"> <view class="header">Header</view> <view class="content"> <slot></slot> </view> <view class="footer">Footer</view> </view>
|
<my-slot> <t-button>按钮</t-button> </my-slot>
|
- 多个插槽,需要给
slot
加上name
属性,用的地方要slot=""
组件 js 里面也要选择使用多插槽
<view class="container"> <view class="left"> <slot name="left"></slot> </view> <view class="center"> <slot name="center"></slot> </view> <view class="right"> <slot name="right"></slot> </view> </view>
|
Component({ options: { multipleSlots: true, }, })
|
<mul-slot> <text slot="left" class="left" >我是左边</text > <text slot="center" class="center" >我是中间</text > <text slot="right" class="right" >我是右边</text > </mul-slot>
|
混入
behaviors
,就像 vue 以前的mixins
一样,现在叫hooks
的多
created
attached
ready
,官方说除了这个的三个比较重要
detached
- 更多见文档
总结
Component
构造器
properties
: 定义传入的属性
data
: 定义内部属性
methods
: 定义方法
options
: 额外配置
externalClasses
: 引用外部样式
observers
: 属性和数据监听
pageLifetimes
: 组件所在页面的生命周期
lifetimes
: 组件生命周期
API 调用
网络请求
wx.request
RequestTask
onLoad() { wx.request({ url: "https://v1.hitokoto.cn/", success: (res) => { const data = res.data; this.setData({ sentence: data.hitokoto }); }, fail: (err) => { console.log("err:", err); }, }); }
|
域名配置
生产环境需要配置只能向固定的域名发动请求,要去小程序后台设置
注意点
- 只支持 https 和 wss
- 不能用 IP 地址
- 可以配置端口,但只能那一个端口了
- 不配置端口的话,请求的 url 中也不能有端口
- 域名要备案
- 不支持配置父域名
封装请求
Promise 封装使用
函数封装
export function myRequest(options) { return new Promise((resolve, reject) => { wx.request({ ...options, success: res => { resolve(res.data) }, fail: reject, }) }) }
|
常规使用
import { myRequest } from '../../service/index'
Page({ data: {}, onLoad() { myRequest({ url: 'https://v1.hitokoto.cn/', }).then(res => { console.log(res) }) }, })
|
async/await 使用,但是不如 promise,必须等前面的请求结束了后面的才发送,效率不高
import { myRequest } from '../../service/index'
Page({ data: {}, async onLoad() { const res = await myRequest({ url: 'https://v1.hitokoto.cn/' }) console.log(res) }, })
|
把请求封装到函数里面,不会堵塞
import { myRequest } from '../../service/index'
Page({ data: {}, onLoad() { this.getData() }, async getData() { const res = await myRequest({ url: 'https://v1.hitokoto.cn/' }) console.log(res) }, })
|
类封装
class HYRequest { constructor(baseURL) { this.baseURL = baseURL }
request(options) { const { url } = options return new Promise((resolve, reject) => { wx.request({ ...options, url: this.baseURL + url, success: res => { resolve(res.data) }, fail: reject, }) }) }
get(options) { return this.request({ ...options, method: 'get' }) }
post(options) { return this.request({ ...options, method: 'post' }) } }
export const hyRequest = new HyRequest()
|
弹窗调用
showToast
,showModol
,showLoading
,showActionSheet
微信文档
分享回调
onShareAppMessage
,监听用户点击转发按钮(button
的 open-type="share"
),或者右上角菜单的转发,并自定义内容
需要return
一个Object
自定义转发内容
onShareAppMessage() { return { title: "转发", path: "/pages/index/index", imageUrl: "自定义图片路径,可不选", }; },
|
获取设备信息
用户信息
onGetUserInfo() { wx.getUserInfo({ success: (res) => { console.log(res); }, }); },
onGetUserProfile() { wx.getUserProfile({ desc: "test", success: (res) => { console.log(res); }, fail: (err) => { console.log(err); }, }); },
|
onGetSystemInfo() { wx.getSystemInfo({ success: (res) => { console.log(res); }, }); },
onGetLocation() { wx.getLocation({ success: (res) => { console.log(res); }, }); },
|
Storage 存储
同步存取数据:执行完上一行才执行下一行
wx.setStorageSync(string key, any data)
wx.getStorageSyne(string key)
wx.removeStorageSync(string key)
wx.clearStorageSync()
异步存取:适用于一个地方存,另一个地方取
wx.setStorage(Object objece)
wx.getStorage(Object objece)
wx.removeStorage(Object objece)
wx.clearStorage(Object objece)
Page({ onLocalStorage() { wx.setStorageSync('name', 'die') wx.setStorageSync('age', 18) wx.setStorageSync('work', ['die', 'for']) }, onClearStorage() { wx.clearStorageSync() }, onLocalStorageAsync() { wx.setStorage({ key: 'books', data: ['vue', 'react'], success: res => { console.log(res) }, }) }, onClearStorageAsync() { wx.clearStorage() }, })
|
名称 |
功能说明 |
wx.switchTab |
跳转到 tabBar 页面,关闭其他所有非 tabBar 页面 |
wx.reLaunch |
关闭所有页面,打开到应用内的某页面 |
wx.redirectTo |
关闭当前页面,跳转到新页面 |
wx.navigateTo |
保留当前页面,跳转到新页面 |
wx.nabitageBack |
关闭当前页面,返回上个页面或多级页面 |
navigateTo
- ==不能跳到 tabBar 页面==
- ==页面栈最多十层==
onNextPage() { const data = "sss"; wx.navigateTo({ url: `/pages/10_learn/index?data=${data}`, }); },
|
数据传递