图网习惯于在做小程序之前先做成html5+vuejs的形式,因为html5切图是我们比较熟悉的方式,而且有专业的工具 以及浏览器调试也会更加的方便 灵活,效率高,而且html5的方式可以方便预览看效果,方便调整,当html5页面做好确认没问题以后 再转成小程序或者官方出品wepy的方式,这个时候就需要找到html5和小程序之间的微妙不同,需要做以下调整,亲测可用。
css需要调整的
把css中的px改为rpx,可以借助工具批量替换,如果使用的工具是 vscode 可以用插件 px to rpx,如果是hbuilder可以执行批量替换。
html需要调整的
js需要调整的
this.$router.push({
path: ‘/course-detail’,
query: {
caseCode: ‘123’
}
})
挑战30天在头条写日记#
WePY (发音: /'wepi/)是一款让小程序支持组件化开发的框架,通过预编译的手段让开发者可以选择自己喜欢的开发风格去开发小程序。框架的细节优化,Promise,Async Functions 的引入都是为了能让开发小程序项目变得更加简单,高效。
同时 WePY 也是一款成长中的框架,大量吸收借鉴了一些优化前端工具以及框架的设计理念和思想。如果 WePY 有不足地方,或者你有更好的想法,欢迎提交 ISSUE 或者 PR。
<style lang="less">
@color: #4D926F;
.num {
color: @color;
}
</style>
<template>
<div class="container">
<div class="num" @tap="num++">
{{num}}
</div>
<custom-component></custom-component>
<vendor-component></vendor-component>
<div>{{text}}</div>
<input v-model="text"/>
</div>
</template>
<config>
{
usingComponents: {
customComponent: '@/components/customComponent',
vendorComponent: 'module:vendorComponent'
}
}
</config>
<script>
import wepy from '@wepy/core';
wepy.page({
data: {
num: 0,
text: 'Hello World',
},
});
</script>npm install @wepy/cli@next -gwepy init standard myprojectcd myproject
npm installwepy build --watch使用微信开发者工具新建项目,本地开发选择项目根目录,会自动导入项目配置。
我们称微信客户端给小程序所提供的环境为宿主环境。小程序借助宿主环境提供的能力,可以完成许多普通网页无法完成的功能。 更多小程序原理的相关知识可参考小程序官方文档。
原生小程序中,每个页面拥有独自的一个页面实例 Page,整个小程序只有一个 App 实例,是全部页面共享的。
同样的,在 WePY 的环境当中,每个 WePY 页面拥有独自的 WepyPage 实例。小程序也会有 WepyApp 实例。它们并非是继承自原生的 Page 和 App。WePY 提供 wepy.app,wepy.page,wepy.component 等入口 方法注册程序、页面、以及组件。注册后在组件的生命周期事件(onLaunch/onLoad/created)里,会自动创建相对应的 WePY 实例。
<!-- app.wpy -->
<script>
import wepy from '@wepy/core'
wepy.app({
// 选项
})
</script>使用入口方法注册 App 时,可以传入一个参数对象。这篇教程主要描述的就是如何使用这些选项来创建你想要的行为。
<!-- app.wpy -->
<config>
{
"pages": [
"pages/example"
]
}
</config><!-- pages/example.wpy -->
<script>
import wepy from '@wepy/core'
wepy.page({
// 选项
})
</script>注册 Page 时,可以传入一个参数对象。这篇教程主要描述的就是如何使用这些选项来创建你想要的行为。
WePY 2.0 中,Page 同样是使用小程序原生的 Component 方法进行注册的。
<!-- components/comA.wpy -->
<script>
import wepy from '@wepy/core'
wepy.component({
// 选项
})
</script><!-- pages/example.wpy -->
<config>
{
"usingComponents": {
"comA": "components/comA"
}
}
</config>与 WePY 1 或者 Vue 不同的是,组件的引用方式保留了原生的 usingComponents 方式。不可以使用 import 的方式导入。
使用 wepy.page 或者 wepy.component 注册页面或者组件时,它将 data 对象中的所有的属性加入到 wepy 的 响应式系统 中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
wepy.page({
data: {
a: 1
},
plus: function () {
// 点击 “+“ 按钮式触发
this.a++
}
})当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时 data 中存在的属性才是响应式的。也就是说如果你添加一个新的属性,比如:
wepy.page({
data: {
a: 1
},
plus: function () {
// 点击 “+“ 按钮式触发
this.a++
},
sayHi: function () {
this.b = 'hi'
}
})那么对 b 的改动将不会触发任何视图的更新。如果你知道你会在晚些时候需要一个属性,但是一开始它为空或不存在,那么你仅需要设置一些初始值。比如:
wepy.page({
data: {
newTodoText: '',
visitCount: 0,
hideCompletedTodos: false,
todos: [],
error: null
}
})WePY 单文件组件主要由 <script>,<template>,<style>,<config> 四部分组成(也包括小程序 <wxs> 标签)。
wepy.app 注册 App 是直接调用原生 App 方法进行 App 注册,生命周期与原生一致。可参见官方文档 App
wepy.page 本质上也是调用原生方法 Component 注册页面,因此它包含了 Component 的完整生命周期。同时,为了兼容对原有 Page 的使用习惯,也保留了所有 Page 特有的生命周期事件。
通过 Page({}) 注册页面 | 通过 wepy.page({}) 注册页面 | 说明 |
onLoad | onLoad | 参看官方文档 Page |
onShow | onShow | 同上 |
onReady | onReady | 同上 |
onHide | onHide | 同上 |
onUnload | onUnload | 同上 |
onPullDownRefresh | onPullDownRefresh | 同上 |
onReachBottom | onReachBottom | 同上 |
onShareAppMessage | onShareAppMessage | 同上 |
onPageScroll | onPageScroll | 同上 |
onResize | onResize | 同上 |
onTabItemTap | onTabItemTap | 同上 |
onAddToFavorites | onAddToFavorites | 同上 |
- | created | 参看官方文档 Component |
- | attached | 同上 |
- | ready | 同上 |
- | moved | 同上 |
- | detached | 同上 |
- | error | 同上 |
wepy component 实例生命周期与原生小程序的 组件生命周期 一致,在 wepy component 实例中,您可以使用如下生命周期钩子:
wepy.component 注册组件除了原生的 Component 生命周期外,还定义了某些其它生命周期。
通过 Component({}) 注册页面 | 通过 wepy.component({}) 注册页面 | 说明 |
- | beforeCreate | 本质上与wepy.created 一样都是在 Component.created 阶段触发,但 wepy.beforeCreate 在 Component.created 刚进入时触发,然后进行 WePY 的 data, props, methods 等等初始化,完成后再触发 wepy.created |
created | created | 参看官方文档 Component |
attached | attached | 同上 |
ready | ready | 同上 |
moved | moved | 同上 |
detached | detached | 同上 |
error | error | 同上 |
不排除一些情况,小程序进行版本库升级后,添加或者删除了新的生命周期函数,而且 WePY 并没有及时的进行更新,而且导致无法使用最新的生命周期函数。在这种情况下,开发者通过参数自行添加最新的生命周期函数。使用方法如下:
wepy.app({ ... }, {
lifecycle: {
// 定义要添加生命周期到 app 或者 page 或者 component
// 值类型为:String 或者 Array 或者 Function
// 值为需要添加的生命周期一个或者多个函数名,或者返回生命周期的函数数组的方法
app: 'onSomeTime', // 给 App 添加一个 `onSomeTime` 生命周期函数
page: ['onTime1', 'onTime2'], // 给 Page 添加两个生命周期函数
component: function (lifecycles) { // 删除 Component 最后一个生命周期函数
lifecycles.pop();
retrun lifecycles;
}
}
})下图展示了 页面/组件 实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
WePY 继承了 WXML 的基本模板语法,并支持大部分 Vue 模板语法。
WXML(WeiXin Markup Language)是框架设计的一套标签语言,用来描述小程序页面的结构
同时,WePY 允许你使用大部分 HTML 模板标签,经编译器编译后,会将模板标签的转换成标准的 WXML 模板语法。
标签 | 转换后 |
select | picker |
datalist | picker |
img | image |
source | audio |
video | video |
track | video |
a | navigator |
span | label |
其它 | view |
以下案例均使用 HTML 模板标签作为参考
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
<div>hello, {{ name }}</div>Mustache 标签将会被替代为对应数据对象上 name 属性的值。无论何时,绑定的数据对象上 name 属性发生了改变,插值处的内容都会更新。
<div v-bind:id="id"></div>此时不能使用 Mustache 语法
<div id="{{ id }}"></div>此时必须使用 Mustache 语法
<div v-if="condition"></div>此时不能使用 Mustache 语法
<div wx:if="{{ condition }}"></div>此时必须使用 Mustache 语法
两种方式均不能使用 Mustache 语法
<div v-on:tap="tapHandler"></div>
<!-- or -->
<div @tap="tapHandler"></div><div bindtap="tapHandler"></div>可以在 {{}} 内进行简单的运算,目前支持原生小程序的所有运算方式,如下:
{{ ok ? 'YES' : 'NO' }}{{ a + b }}{{ length > 5 }}{{ "hello" + name }}{{ object.key }}
{{ array[0] }}也可以在 Mustache 内直接进行组合,构成新的对象或者数组,详情请阅读 小程序官方文档
WePY 推荐使用 v-show,v-if 控制条件渲染
// example 01
<div wx:if="{{ condition }}"></div>
// example 02
<div wx:if="{{ condition2 }}"></div>
<div wx:else></div>
// example 03
<div wx:if="{{ condition3 }}"></div>
<div wx:elif="{{ condition4 }}"></div>
<div wx:else></div><div hidden="{{ condition }}"></div>// example 01
<div v-if="condition"></div>
// example 02
<div v-if="condition2"></div>
<div v-else></div>
// example 03
<div v-if="condition3"></div>
<div v-else-if="condition4"></div>
<div v-else></div>编译后:
// example 01
<view wx:if="{{ condition }}"></view>
// example 02
<view wx:if="{{ condition2 }}"></view>
<view wx:else></view>
// example 03
<view wx:if="{{ condition3 }}"></view>
<view wx:elif="{{ condition4 }}"></view>
<view wx:else></view><div v-show="condition"></div>编译后:
<view hidden="{{ !condition }}"></view>WePY 2 推荐使用 Vue v-for 指令进行列表渲染
编译前:
// example 01
<div v-for="item in array">{{index}}: {{item.message}}</div>
// example 02
<div v-for="(item, idx) in array">
{{idx}}: {{itemName.message}}
</div>编译后:
// example 01
<view wx:for="{{array}}">{{index}}: {{item.message}}</view>
// example 02
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName.message}}
</view>未特殊提及的信息可优先参考 vue官方文档
小程序原生的事件系统 使用bind,catch 等关键字进行事件监听。 而在 WePY 中,事件沿用了 Vue 的风格,使用 v-on 或者是 @ 操作符进行事件监听。同时 WePY 中会有一个统一的事件分发器接管原生事件。大致如下图:
WePY 在编译过程中,会找到所有监听事件,并为其分配事件 ID。同时将事件代码(可以是一个方法,也可以是一个简单的代码片段)注入至 JS 代码中。 然后当事件分发器接收到原生事件时,会通过事件 ID,分发到相应的事件逻辑当中。
这样做的好处主要是:
WePY 不仅可以支持到响应事件监听,也可以支持到像 Web 原生,或者 Vue 的那种,使用简单代码片段的监听方式,示例如下:
<template>
<!-- 使用代码片段响应事件 -->
<button @tap="num =+ 1">Counter - {{num}}</button>
<!-- 类原生方式,使用事件函数响应事件 -->
<button @tap="handler">Handle my event</button>
<!-- 类Vue方式,原生不支持携带参数 -->
<button @tap="handlerWithArgs(1, 2)">Handle my event with arguments</button>
</template>
<script>
import wepy from '@wepy/core';
wepy.page({
data: {
num: 0,
},
methods: {
handler() {
// do something
},
handlerWithArgs(a, b) {
console.log(a, b);
}
}
})
</script>注: 原生小程序中使用 <div data-hi="1"></div> 的方式传递参数,然后使用 event.currentTarget.dataset.hi 的方式获取参数。 在 WePY 中请尽量使用携带参数响应事件去完成参数的传递与获取。WePY 会在编译时为你绑定 data-xxx 并且在事件分发器中贴心的为你处理好参数的。
小程序原生事件会传递一个 event 参数。而 WePY 的事件分发器在处理事件时会有一个 $event 参数。 $event 参数是对 event 进行了一层包装,目地是为了无侵入地对齐 Web Event 标准属性。而其中 $event.$wx === event。 因此,WePY 中响应事件获得的事件参数均是指 $event。如果想拿到原生事件参数,请使用 $event.$wx。
当使用类原生方式,使用响应事件方法名进行事件监听时,响应事件会接收到一个 $event 参数。 当使用带参函数进行事件监听时,默认不会拿到事件的 $event。 该行为与 Vue 行为是一致的。此时若想拿到 $event 需要指定 $event 参数。
示例:
<!-- click 会接收到一个 $event 参数 -->
<button @tap="click">Click</button>
<!-- click 会接收一个为 1 的参数 -->
<button @tap="click(1)">Click</button>
<!-- click 会接受两个参数: 1, $event -->
<button @tap="click(1, $event)"小程序的事件系统中,可以使用 bind, catch, capture-bind, capture-catch 等来处理事件的冒泡与捕获,其中区别请参考官方文档。
在 WePY 中,使用修饰符来完成这一动作,相对来说更加灵活与易读。示例:
<!-- 等同于 bind:tap -->
<div @tap="myclick"></div>
<!-- 等同于 catch:tap -->
<div @tap.stop="myclickStop"></div>
<!-- 等同于 capture-bind:tap -->
<div @tap.capture="myclickCapture"></div>
<!-- 等同于 capture-catch:tap -->
<div @tap.stop.capture="myclickCaptureStop"></div>
<!-- 等同于 capture-catch:tap 修饰符中无先后关系 -->
<div @tap.capture.stop="myClickCaptureStopWithParams"></div>
作用:标识取消事件冒泡,对应原生事件中的 catch
在下边这个例子中,点击 inner view 会先后调用 handleTap3 和 handleTap2 (因为tap事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发 handleTap2,点击 outer view 会触发 handleTap1。
<div id="outer" @tap="handleTap1">
outer view
<div id="middle" @tap.stop="handleTap2">
middle view
<div id="inner" @tap="handleTap3">
inner view
</div>
</div>
</div>
作用:标识事件捕获阶段,对应原生事件中的 capture-xxxx
捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用 .capture、.capture.catch 修饰符,后者将中断捕获阶段和取消冒泡阶段。
在下面的代码中,点击 inner view 会先后调用 handleTap2、handleTap4、handleTap3、handleTap1。
<div id="outer" @touchstart="handleTap1" @touchstart.capture="handleTap2">
outer view
<div id="inner" @touchstart="handleTap3" @touchstart.capture="handleTap4">
inner view
</div>
</div>如果将上面代码中的第一个 capture 后面加一个 catch 修饰符,将只触发 handleTap2。
<div id="outer" @touchstart="handleTap1" @touchstart.capture.catch="handleTap2">
outer view
<div id="inner" @touchstart="handleTap3" @touchstart.capture="handleTap4">
inner view
</div>
</div>作用:标识使用WXS函数响应事件
小程序基础库 2.4.4 开始支持,低版本需做兼容处理
wxs 响应事件的背景及实现方案,参考 小程序官方文档
<wxs module="test" src="./test.wxs"></wxs>
<div change:prop="{{test.propObserver}}" :prop="propValue" @touchmove.wxs="test.touchmove" class="movable"></div>
上面的 change:prop(属性前面带 change: 前缀)是在 prop 属性被设置的时候触发 WXS 函数,值必须用{{}}括起来。在 propValue 值发生变化之后会触发。
当 prop 属性的值被设置 WXS 函数就会触发,而不只是值发生改变,所以在页面初始化的时候会调用一次 WXS 中 propObserver 的函数。
WXS 文件 test.wxs 里面定义并导出事件处理函数和属性改变触发的函数:
module.exports = {
touchmove: function(event, instance) {
console.log('log event', JSON.stringify(event))
},
propObserver: function(newValue, oldValue, ownerInstance, instance) {
console.log('prop observer', newValue, oldValue)
}
}
作用:标识使用互斥事件
小程序基础库 2.8.2 开始支持,低版本需做兼容处理 该修饰符 WePY 暂不支持
v-model 本质上是语法糖,它会根据控件类型自动选取正确的方法来更新元素
<input v-model="inputmodel" />
<script>
import wepy from '@wepy/core';
wepy.page({
data: {
inputmodel: ''
}
})
</script><textarea v-model="inputmodel" />
<script>
import wepy from '@wepy/core';
wepy.page({
data: {
inputmodel: ''
}
})
</script><picker v-model="pickermodel" range="{{array}}">
<div class="picker">
当前选择:{{pickermodel}}
</div>
</picker>
<script>
import wepy from '@wepy/core';
wepy.page({
data: {
array: ['美国', '中国', '巴西', '日本'],
pickermodel: ''
}
})
</script>
<switch v-model="switchmodel" />
<script>
import wepy from '@wepy/core';
wepy.page({
data: {
switchmodel: ''
}
})
</script>小程序的radio目前不支持 change 事件, 请使用radio-group标签
<radio-group v-model="radiomodel">
<label>
<div>
<radio value="美国"></radio>
</div>
</label>
</radio-group>
<script>
import wepy from '@wepy/core';
wepy.page({
data: {
radiomodel: ''
}
})
</script>小程序的checkbox目前不支持 change 事件, 请使用checkbox-group标签
<checkbox-group v-model="checkboxmodel">
<label>
<div>
<checkbox value="美国"></checkbox>
</div>
</label>
</checkbox-group>
<script>
import wepy from '@wepy/core';
wepy.page({
data: {
checkboxmodel: ''
}
})
</script>https://github.com/Tencent/wepy
文件后缀为.wpy,可共用vue高亮,但需要手动安装。
打开Sublime->Preferences->Browse Packages..进入用户包文件夹。
在此文件夹下打开cmd,运行
git clone git@github.com:vuejs/vue-syntax-highlight.git,无GIT用户可以直接下载zip包解压至当前文件夹。
关闭.wpy文件重新打开即可高亮。
打开Preferences,搜索Plugins,搜索Vue.js插件并安装。
打开Preferences,搜索File Types,找到Vue.js Template,在Registered Patterns添加*.wpy,即可高亮。
在Atom里先安装vue的语法高亮 - language-vue,如果装过了就忽略这一步。
打开Atom -> Config菜单。在core键下添加:
customFileTypes:
"text.html.vue": [
"wpy"
]
在vscode里先安装vue的语法高亮 - language-vue,如果装过了就忽略这一步。
在项目根目录下,建立.vscode目录
在.vscode里建立settings.json文件,内容如下:
{
"git.ignoreLimitWarning": true,
"files.associations": {
"*.wxml": "html",
"*.wxss": "css",
"*.wpy": "vue"
}
}
*请认真填写需求信息,我们会在24小时内与您取得联系。