- Published on
微信小程序框架Wepy的一些坑
- Authors

- Name
- Simmzl
相较于原生将js、wxss、wxml、json配置分开,wepy采用单文件模式,很贴近vue语法,对es6、css预处理器等的支持效率提升很多,但是坑也是有很多,记录下避免重复踩坑浪费时间。
页面实例与组件实例继承要对应
在写组件时把组件写成继承自wepy.page,导致组件无法渲染
// 页面继承自wepy.page
export default class Index extends wepy.page {}
// 组件继承自wepy.component
export default class Card extends wepy.component {}
Page页面实际上继承自Component组件,即Page也是组件。除扩展了页面所特有的config配置以及特有的页面生命周期函数之外,其它属性和方法与Component一致,但声明继承不能错。
import wepy from 'wepy';
export default class MyPage extends wepy.page {
// export default class MyComponent extends wepy.component {
config = {}; // 只在Page实例中存在的配置数据,对应于原生的page.json文件
customData = {} // 自定义数据
data = {}; // 页面所需数据均需在这里声明,可用于模板数据绑定
components = {}; // 声明页面中所引用的组件,或声明组件中所引用的子组件
mixins = []; // 声明页面所引用的Mixin实例
computed = {}; // 声明计算属性(详见后文介绍)
watch = {}; // 声明数据watcher(详见后文介绍)
methods = {}; // 声明页面wxml中标签的事件处理函数。注意,此处只用于声明页面wxml中标签的bind、catch事件,自定义方法需以自定义方法的方式声明
events = {}; // 声明组件之间的事件处理函数
customFunction () {} //自定义方法
onLoad () {} // 在Page和Component共用的生命周期函数
onShow () {} // 只在Page中存在的页面生命周期函数
}
props静态与动态传值
静态传值为父组件向子组件传递常量数据,因此只能传递String字符串类型
<child title="mytitle"></child>
动态传值像Vue,但是传的数据需要是在父组件声明过或者引用类型,不能直接传Boolean、Number等基础类型
// 正确:
<child :title="parentTitle" :syncTitle.sync="parentTitle" :twoWayTitle.sync="parentTitle"></child>
data = {
parentTitle: 'p-title'
};
// child.wpy
props = {
// 静态传值
title: String,
// 父向子单向动态传值
syncTitle: {
type: String,
default: 'null'
},
twoWayTitle: {
type: String,
default: 'nothing',
twoWay: true
}
};
// 错误 不能动态传值传基础类型,必须声明
<child :myNumber="12" :myNumber1.sync="12" :isTrue="true"></child>
同一页面重复引用同一组件相关问题
循环渲染使用<repeat>
循环渲染组件时必须使用wepy特有的辅助标签<repeat>,而不是使用原生的wx:for
<repeat for="{{list}}" key="index" index="index" item="item">
<!-- 插入<script>脚本部分所声明的child组件,同时传入item -->
<child :item="item"></child>
</repeat>
<script>
import wepy from 'wepy';
import Child from './child';
export default class Index extends wepy.page {
// 声明组件ID为child
components = {
child: Child
}
data = {
list: [{id: 1, title: 'title1'}, {id: 2, title: 'title2'}]
}
}
</script>
重复引用需为每个组件声明ID
Wepy中的组件都是静态组件,是以组件ID作为唯一标识的,每一个ID都对应一个组件实例。 当页面引入两个相同ID的组件时,这两个组件共用同一个实例与数据,当其中一个组件数据变化时,另外一个也会一起变化。
这也是不同于vue的地方,当同一页面使用同一组件较多次时,这就很难受了。
如果需要避免这个问题,必须需要分配多个组件ID和实例:
<template>
<view class="child1">
<form-item1></form-item1>
<form-item2></form-item2>
</view>
</template>
<script>
import wepy from 'wepy';
import FormItem from './formItem';
export default class Index extends wepy.page {
components = {
//为两个相同组件的不同实例分配不同的组件ID,从而避免数据同步变化的问题
"form-item1": FormItem,
"form-item2": FormItem
};
}
</script>
组件内动态绑定class,且类名含"-"时,渲染会自动加上ID
// index.wpy
<template>
<view>
<form-item1 :isActive.sync="isActive"></form-item1>
<form-item2></form-item2>
</view>
</template>
<script>
import wepy from 'wepy';
import FormItem from './formItem';
export default class Index extends wepy.page {
data = {
isActive: true
}
components = {
//为两个相同组件的不同实例分配不同的组件ID,从而避免数据同步变化的问题
"form-item1": FormItem,
"form-item2": FormItem
};
}
</script>
// formItem.wpy
<template>
<view :class="{"vk-activity': isActive}"></view>
</template>
<script>
import wepy from 'wepy';
export default class Index extends wepy.component {
props = {
isActive: {
type: Boolean,
default: false
}
}
}
</script>
最终index.wpy会被渲染成wxml:
<view>
<view class="vk- formItem1 activity"></view>
<view></view>
</view>
解决方法是不用横杠的类名,改用驼峰或单个单词等。
改组件名后,wepy报组件找不到错
改动组件名时wepy有时不会立即生成wxml,这时候看dist生成的wxml是没有文件或者文件不对,可删除dist中的对应wxml文件,手动触发wpy文件改动就可以了。
组件中引用组件时,最底层组件变动有时不会触发上层或上几层页面的热加载
不触发热加载很坑,应该是嵌套多层的原因,ctrl+c再run dev重新跑项目,不行就删了dist中的组件再重新编译。
异步函数中更新数据,必须手动调用$apply(),才会触发脏数据检查
wepy对原生API进行了promise处理,但也有一些问题
在原生API中往往是采用回调的形式:
wx.showModal({
title: "提示",
content: "这是一个模态弹窗",
success(res) {
if (res.confirm) {
console.log("用户点击确定")
} else if (res.cancel) {
console.log"用户点击取消")
}
}
})
在wepy中,配合polyfill可以使用async await处理异步函数;
在app.wpy入口文件中声明:
export default class extends wepy.app {
constructor() {
super();
this.use("requestfix");
// 声明使用promisify
this.use("promisify");
}
}
就可以使用await async了:
async handleXx() {
const res = await wepy.showModal();
if (res.confirm) console.log("用户点击确定");
}
但是部分API还是有问题的,如getUpdateManager();
wepy.getUpdateManager()会返回一个promise,但无resolved,不是updateManager对象。
为此我在wepy github仓库提了一个issue,但是没有维护人员的回复,感觉wepy没人维护了...
解决方法是使用原生方法wx.getUpdateManager()
预先在data中声明值
在dom上使用值做判断时,该值一定要在data里先声明,否则值改变时,dom不会变化