圖網習慣于在做小程序之前先做成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 -g
wepy init standard myproject
cd myproject
npm install
wepy 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小時內與您取得聯系。