微信小程序之:wepy框架
1、介绍
WePY 是 腾讯 参考了Vue 等框架对原生小程序进行再次封装的框架,更贴近于 MVVM 架构模式, 并支持ES6/7的一些新特性。
2、使用
npm install -g wepy-cli //全局安装或更新WePY命令行工具(wepy脚手架): wepy-cli wepy -v //查看wepy-cli版本 wepy init standard <projectName> //新建wepy小程序项目,1.7.0之前的版本使用:wepy new myproject,安装项目翻译一下即可 wepy list //查看项目模板 cd <projectName> //切换至项目目录 npm install //安装依赖 wepy build --watch //开启实时编译
3、规范
①代码规范
wepy和原生标签一样
自定义组件名尽量避开原生组件名、wepy的辅助标签repeat
方法名、变量名尽量使用驼峰命名
文件后缀为.wpy
支持ES6/ES7的一些新特性
继承了wx对象方法,wepy中没有wx对象,尽量不要用到此方法,打包时容易报错
②数据绑定
//原生小程序 this.setData({xxx:xxx}); //wepy data={aaa:''} this.aaa = 'aaa'; //wepy 在异步函数中更新数据的时候,必须手动调用$apply方法,才会触发脏数据检查流程的运行 this.$apply();
③事件绑定以及时间传参
<view @tap="click"></view> // 原 bindtap="click"(省略了.default后缀 )绑定小程序冒泡型事件 <view @tap.stop="click"></view> // 原catchtap="click" 绑定小程序捕获型事件,如catchtap <view @tap.capture="click"></view> // 原 capture-bind:tap="click" <view @tap.capture.stop="click"></view> // 原 capture-catch:tap="click" <!--事件传参--> <view @tap="click({{index}})"></view> // 原bindtap="click" data-index={{index}}
④框架默认对小程序的API提供了Promise处理,可以直接调用async/await直接开发
// 原生代码: wx.request({ url: 'xxx', success: function (data) { console.log(data); } }); // WePY 使用方式, 需要开启 Promise 支持,参考开发规范章节 wepy.request('xxxx').then((d) => console.log(d)); // async/await 的使用方式, 需要开启 Promise 和 async/await 支持,参考 WIKI async function request () { let d = await wepy.request('xxxxx'); console.log(d); }
//需要开启Promise的解释
//1、进入项目目录,安装polyfill
npm install wepy-async-function --save
//2、在app.wpy中导入polyfill
import 'wepy-async-function';
//3、在app.wpy中使用promiss
constructor () { super(); this.use('promisify'); }
//4、判断是否引入成功
onLaunch() { console.log('on launch'); let mypro = new Promise((resolve, reject) => { setTimeout(() => { resolve(123); }, 2000); }); mypro.then((r)=>{ console.log(r); }) }
//重启编译
//打印出内容即为成功
⑤computed计算属性,类型{ [ key:string ] : function },有返回值,绑定数据使用,
data={aaa:1}; // 计算属性aPlus,在脚本中可通过this.aPlus来引用,在模板中可通过{{ aPlus }}来插值 computed={ aPlus(){ return this.a+1 } };
⑥watcher监听,类型{ [ key:string ] : function },监听任何属性更新,处理数据专用。
data={ aaa:'xxx' }; // 监听器函数名必须跟需要被监听的data对象中的属性同名, // 其参数中的newValue为属性改变后的新值,oldValue为改变前的旧值
// 每当监听属性aaa改变一次,该函数就调用一次 watch={ aaa(newValue,oldValue){ console.log(`data的aaa由${oldValue}变为${newValue}`) } }
⑦wxs
等待学习
⑧interceptor拦截器
可以对原生api进行请求拦截,具体方法是配置api的config、fail、success、complete回调函数。
//app.wpy constructor () { //在super()是不允许的 super() //拦截request请求 this.intercept('request',{ //发出请求时的回调函数 config(res){ //对所有请求附加token res.token = token; return res; } //请求成功后的回调函数 success(res){ return res; } //请求失败后的回调函数 fail(res){ return res; } //请求完成后的回调函数 complete(res){ return res; } }); }
4、项目目录结构
原生小程序:app(app.js
、app.json
、app.wxss)
,page(page.js
、page.json
、page.wxml
、page.wxss),
文件必须同名。
WePY中则使用了单文件模式:app.wpy
,page.wpy
。
一个.wpy
文件可分为三大部分,各自对应于一个标签:
- 脚本
<script>
部分,又可分为两个部分:
逻辑部分,除了config对象之外的部分,对应于原生的.js
文件
配置部分,即config对象,对应于原生的.json
文件
-
结构
<template>
部分,对应于原生的.wxml
文件 -
样式
<style>
部分,对应于原生的.wxss
文件
①components组件:
import wepy from 'wepy'; export default class MyComponent extends wepy.component { props = {}//接收父组件传来的参数 customData = {} // 自定义数据 customFunction () {} //自定义方法 onLoad () {} // 在Page和Component共用的生命周期函数 data = {}; // 页面所需数据均需在这里声明,可用于模板数据绑定 components = {}; // 声明页面中所引用的组件,或声明组件中所引用的子组件 mixins = []; // 声明页面所引用的Mixin实例 computed = {}; // 声明计算属性(详见后文介绍) watch = {}; // 声明数据watcher(详见后文介绍) methods = {}; // 声明页面wxml中标签的事件处理函数。注意,此处只用于声明页面wxml中标签的bind、catch事件,自定义方法需以自定义方法的方式声明 events = {}; // WePY组件事件处理函数对象,存放响应组件之间通过$broadcast、$emit、$invoke所传递的事件的函数 } /** 与page不同的是component不存在: onShow () {} // 只在Page中存在的页面生命周期函数 config = {}; // 只在Page实例中存在的配置数据,对应于原生的page.json文件,类似于app.wpy中的config onReady() {} // 只在Page中存在的页面生命周期函数 **/
**无法实现组件化的松耦合与复用
(如,模板A中绑定一个bindtap="myclick"
,模板B中同样绑定一样bindtap="myclick"
,那么就会影响同一个页面事件、数据)
a、引用组件
//引入组件文件 import Child from '../components/child'; export default class Index extends wepy.component { //声明组件,分配组件id为child,需要注意的是,WePY中的组件都是静态组件,是以组件ID作为唯一标识的,
每一个ID都对应一个组件实例,当页面引入两个相同ID的组件时,这两个组件共用同一个实例与数据,当其中一个组件数据变化时,另外一个也会一起变化。 components = { //为两个相同组件的不同实例分配不同的组件ID,从而避免数据同步变化的问题 child: Child, }; }
//在html中使用组件
<child></child>
②页面page.wpy
Page页面实际上继承自Component组件,即Page也是组件。
除扩展了页面所特有的config
配置以及特有的页面生命周期函数之外,其它属性和方法与Component一致:
import wepy from 'wepy'; export default class MyPage extends wepy.page { customData = {} // 自定义数据 customFunction () {} //自定义方法 onLoad () {} // 在Page和Component共用的生命周期函数 onUnload() {} // 监听页面卸载 onReady() {} // 只在Page中存在的页面生命周期函数 onShow () {} // 只在Page中存在的页面生命周期函数,当小程序启动,或从后台进入前台显示 onHide() {} // 只在Page中存在的页面生命周期函数,当小程序从前台进入后台 config = {}; // 只在Page实例中存在的配置数据,对应于原生的page.json文件,类似于app.wpy中的config data = {}; // 页面所需数据均需在这里声明,可用于模板数据绑定 components = {}; // 声明页面中所引用的组件,或声明组件中所引用的子组件 mixins = []; // 声明页面所引用的Mixin实例 computed = {}; // 声明计算属性 watch = {}; // 声明数据watcher methods = {}; // 声明页面wxml中标签的事件处理函数。注意,此处只用于声明页面wxml中标签的bind、catch事件,自定义方法需以自定义方法的方式声明 events = {}; // WePY组件事件处理函数对象,存放响应组件之间通过$broadcast、$emit、$invoke所传递的事件的函数 onPullDownRefresh(){} // 监听用户下拉动作 onReachBottom(){} // 页面上拉触底事件的处理函数 onShareAppMessage(){} // 用户点击右上角分享 onPageScroll(){} // 页面滚动 onTabItemTap(){} // 当前是 tab 页时,点击 tab 时触发 }
③状态管理store(redux)
④app.wpy:小程序入口
继承自wepy.app类;包含config配置对象、globalData对象、自定方法属性、小程序生命周期函数;
在page页面中可以使用this.$parent调用实例
<script> import wepy from 'wepy'; export default class extends wepy.app { config = { pages:[// pages定义当前小程序所有页面路径,让微信客户端知道当前你的小程序页面定义在哪个目录 'pages/index', 'pages/mine' ], window:{//window定义小程序所有页面的顶部背景颜色,文字颜色定义等。 "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "顶部标题", "navigationBarTextStyle": "black" }, tabBar: { selectedColor: '#ea9100',//底部导航字体选中时的颜色 list: [ { pagePath: 'pages/index',//导航页面路径(必须在pages中定义) text: '首页',//导航名 iconPath: 'img/index.png',//未选中的导航icon selectedIconPath: 'img/index1.png'//选中时的导航icon }, { pagePath: 'pages/mine', text: '我的', iconPath: 'img/mine.png', selectedIconPath: 'img/mine1.png' } ] }, }; onLaunch() {//初始化 console.log(this); } onShow(){}//当小程序启动,或从后台进入前台显示 onHide(){}//当小程序从前台进入后台 } </script> <style lang="less"> /** less **/ </style>