小程序開發之mpVue


# my-project

> A Mpvue project

## Build Setup

```bash
# install dependencies
npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build

# build for production and view the bundle analyzer report
npm run build --report
```

#項目構建
http://mpvue.com/build/

#mpvue-docs 使用手冊
http://mpvue.com/mpvue

# Flyio Github:

https://github.com/wendux/fly

For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).

#創建一個小程序工程

vue init mpvue/mpvue-quickstart my-project

# 1) package.json

# 項目的主配置文件, 對 mpvue 的描述,項目依賴的各種第三方庫、版本信息、執行的腳本、etc。。

# scripts 中配置的是可執行命令

# dev and start 可以將項目以開發模式啟動

npm start
npm run dev(注意點:新增文件必須重新運行該命令,編譯器不會自動檢測新加入的文件)

# build 用於生成發布所用的代碼,主要對代碼進行壓縮優化。

# lint 指令 使用 ESLint 進行代碼語法和格式檢查,及修復一些可以自動修復的問題

# 檢查語法和格式

npm run lint

# 檢查代碼語法和格式,並修復可自動修復的問題

npm run lint -- --fix

# 2)project.config.json 文件

# 用於管理微信開發者工具的小程序項目的配置文件,記錄了小程序的 appid、代碼主目錄、以及編譯選項。導入小程序項目的時候主要是通過該配置文件讀取和寫入配置信息

# 3)static 目錄

# 用於存放各種小程序本地靜態資源;圖片、文本文件,可通過相對路徑或絕對路徑進行訪問

# 4) build 目錄

#用於項目編譯打包的 node.js 腳本和 webpack 配置文件

# 5)config 目錄

# 用於開發和生產環境下的不同配置

dev.env.js用於開發環境
prod.env.js用於生產環境

# const baseURL = process.env.API_BASE_URL

# wx.request({

# url: `${baseURL}/products`

# })

# 6)src 目錄

#components:vue 組件存放的目錄
#pages:存放小程序的頁面,請遵循每個小程序頁面放入一個單獨子目錄的組織形式
#utils:可選,存放代碼中公用工具函數
#main.js 和 App.js:入口文件

# 7) app.json 是小程序的全局配置文件,

{
1. 頁面文件路徑配置 pages
2. 窗口的全局樣式信息 window
3. 底部選項卡式菜單欄的配置
4. 及一些小程序網絡超時的配置
5. ....etc
}

# 配置詳情參考 小程序官網文檔

https://developers.weixin.qq.com/miniprogram/dev/framework/config.html#全局配置

# src/main.js 中,小程序的配置信息

# 8)app.js 包含在小程序各種原生生命周期函數,如 onLaunch、onShow 等

在 mpvue 中,使用 App.vue 組件實現等價功能在 App.vue 組件中可以編寫小程序的生命周期方法(通常使用 vue 生命周期方法,同時兼容原生生命周期函數);亦可加入小程序的全局樣式(等價於原生中的 app.wxss),一起看下 App.vue 文件

接下來,App.vue 組件被 src/main.js 引入並被設置了一個 mpType 的屬性值,其值為 app

疑問:mpType 是什么?為什么要用?怎么用? 后續我們再說明下,騷年等等先

#這里提到了組件,組件特點有哪些?

1.封裝性(使用.vue 文件形式){
注意:避免向外暴露過多,只需要必要的交互接口(如:組件屬性、事件、方法),外部調用不需要關心組件內部實現細節,只關心功能即可
}

2.復用性{
多次使用,避免編寫重復的代碼
}
3.擴展性{
1.繼承是一種比較有效的擴展機制,不過隨着繼承的層次變深,代碼也會變得難以理解
2.vue組件中,沒有采用繼承的機制,而是推薦使用“組合”的方式?
如何組合?{
***盡量將想復用性高的組件設計到最小可拆分單位(如按鈕、輸入框、單選框等)
將其低層組件放入更高層組件中,一層一層組裝出滿足業務需求的界面
}
除此之外,vue為我們提供了slot插槽,具體如何使用呢?看代碼 pages/slot
{
理解為組件中的坑,我們可以選擇往坑里扔哪些內容來填充
***slot用於子組件中
{
插槽就是另外一種形式的組件屬性,
普通組件屬性傳入的是比較簡單類型的數據,
插槽傳入的可以是復雜的界面組件
}
}
}

# 代碼更加容易理解和維護、提升了代碼的健壯性、會降低 bug 出現的幾率(容易定位和調試)

}

# 9)遵循每個頁面放入一個子目錄的習慣(原生小程序習慣)

該子目錄下,新建 2 個文件:
{ 1. 用於實現頁面主體功能的 index.vue 組件 2. 用於將這個頁面組件生成 Vue 實例並加載的 main.js
}

注:每個 mpvue 頁面組件都是這樣的結構(查看 pages 目錄下的文件了解下)

實現 index.vue 頁面組件,寫法和 vue 組件一樣優點:
{ 1.數據綁定、事件處理、scoped 局部樣式、以及使用 HTML 標簽來構建界面 2.減少了項目切換到小程序時的學習理解成本 3.使用 Vue 開發的網頁應用移植到小程序平台提供了降低遷移成本的可能
}

模板部分我們通常可以用 HTML 標簽來寫,比如 div、span 等,它們會在編譯的時候被自動轉換成小程序的原生組件 view、text 之類;而那些小程序特有的組件如 swiper、rich-text 等,可以直接在模板中使用

注意:{
在原生小程序的頁面(Page)中包含了很多頁面的生命周期方法,如 onLoad、onUnload、onShow、onHide、onPullDownRefresh 等等,mpvue 中推薦使用 Vue 組件生命周期方法,而像 onPullDownRefresh、onReachBottom 這類特殊功能的生命周期則需直接使用原生的
}

# 小程序一般會有多個頁面構成,在 src/pages 目錄下編寫多個頁面組件后,mpvue 會自動把它們都添加進配置文件,此時注意一點小程序的機制: 配置文件中 pages 數組里的第一個 page 路徑會被當做是首頁

#如果我們期望的首頁組件並沒有被 mpvue 添加到第一個路徑的話,就不會被當做首頁顯示解決方法:{ 1.顯示的去指定首頁在 src/main.js 的配置里,加入這樣一行配置信息:
pages: [
'^pages/index/main'
]
}
注意:十分火急,目前版本這種解決方案存在 bug,老版本的可以,需要等到新版本穩定后待解決。最后建議,在 app.json 中 pages 就指定好首頁。

########由於小程序框架本身存在的一些功能限制,導致有些功能不能被翻譯過去,也就是說有些標准的 Vue 功能在 mpvue 下是不可以使用或有特殊限制的

##################################################################################################### #需要注意的點有哪些?

#1.在模板中,動態插入 HTML 的 v-html 指令不可用
{ 小程序的界面並不是基於瀏覽器的 BOM/DOM 的,所以不能動態的在界面模板里直接插入 HTML 片段來顯示

# 如果有需求怎么辦?使用<rich-text>組件

# 或者 wxParse(https://github.com/icindy/wxParse)實現

}

#2.在模板中,用於數據綁定的雙括號語法{{}}中的表達式功能存在諸多限制
{
只能在雙括號中使用一些簡單的運算符運算(+ - \* % ?: ! == === > < [] .)

# 解決方案,盡量考慮使用計算屬性(computed)

}

#3.在模板中,除事件監聽外,其余地方都不能調用 methods 下的函數
{
如:v-if 指令中調用函數 getErrorNum()

<div v-if="getErrorNum() > 0 && code == 10001" class="error">{{ errorMsg }}</div>

#解決方案暫時還是計算屬性
}

#4.在模板中,不支持直接綁定一個對象到 style 或 class 屬性上

在 Vue 中我們可以為 HTML 元素的 class 或 style 綁定一個對象,並按照對象內的屬性值來決定是否添加對應的屬性名到 HTML 元素的樣式名

```
<template>
<div :class="classObject"></div>
</template>

<script>
export default {
data() {
return {
classObject: {
active: true,
'text-danger': false
}
}
}
}
</script>
```

# 運行后 生成<div class="active"></div>

#在 mpvue 下面這個特性不可以使用官方解決方案{

# <div :class="{ active: classObject.active, 'text-danger': classObject['text-danger']}"></div>

}

# 好的解決方案:使用計算屬性(直接生成一串樣式的字符串,綁定到 class 或 style 上)

```
<template>
<div :class="classStr"></div>
</template>

<script>
export default {
data() {
return {
classObject: {
active: true,
'text-danger': false
}
}
},
computed: {
classStr() {
let arr = []
for (let p in this.classObject) {
if (this.classObject[p]) {
arr.push(p)
}
}
return arr.join(' ')
}
}
}
</script>
```

#5. 在模板中,嵌套使用 v-for 時,必須指定索引 index
之前我們寫 v-for 時, <ul v-for="item in List"></ul>
使用 mpvue,必須 <ul v-for="(item,index) in List " :key="index"></ul>才可以

#6.事件處理中的注意點

在 mpvue 中,一般可以使用 Web 的 DOM 事件名來綁定事件,
mpvue 會將 Web 事件名映射成對應的小程序事件名:
// 左側為 WEB 事件 : 右側為對應的小程序事件

```
{
click: 'tap',
touchstart: 'touchstart',
touchmove: 'touchmove',
touchcancel: 'touchcancel',
touchend: 'touchend',
tap: 'tap',
longtap: 'longtap',
input: 'input',
change: 'change',
submit: 'submit',
blur: 'blur',
focus: 'focus',
reset: 'reset',
confirm: 'confirm',
columnchange: 'columnchange',
linechange: 'linechange',
error: 'error',
scrolltoupper: 'scrolltoupper',
scrolltolower: 'scrolltolower',
scroll: 'scroll'
}
```

#Web 表單組件<input>和<textarea>的 change 事件會被轉為 blur 事件

#Vue 里面綁定事件的時候,可以指定事件修飾符,但是在 mpvue 里,官方給出了一些注意信息: #遇到事件相關的問題,查看一下文檔吧

#7.對於表單,請直接使用小程序原生的表單組件
{
實際開發中,推薦直接使用小程序的表單組件標簽來寫,而不是使用 Web 的表單組件標簽來寫在 mpvue 中使用了小程序的組件標簽,數據綁定功能還是完全可以用的
}

#8.created 不是預期的觸發所有頁面的 created 在小程序初始化時都會觸發,mounted 對應小程序的 onLoad,所以 mpvue mounted 相當於 vue 中的 created

mounted() { // 相對應小程序的 onLoad
// 獲取數據
this.getData();
},

vue 中獲取數據放到 created 中,mpvue 則放到 mounted 中

#9.不支持的 vue 屬性
{

1. keep-alive
2. solt
3. class 和 style 的 classObject 和 styleObject 語法。
4. filters (filters 可以使用 motheds 或者 computed 替換)
}

#10. mpvue-loader 版本 1.1 以上需要新建 main.json 作為配置文件(后續

#11. 圖片使用相對路徑無法加載,放到 dist/static 目錄下使用絕對路徑即可\*\*

#12.新建頁面需要重新 npm run dev 才能生效

#13. 頁面返回后沒有銷毀

{

1. 小程序中頁面返回后該頁面就會出棧,下次進入重新觸發 onLoad
2. mpvue 返回后頁面沒有銷毀,數據會緩存,所以進入頁面我們需要重置數據
}

onLoad() {
// 解決頁面返回后,數據沒重置的問題
Object.assign(this, this.$options.data());
},
methods: {

},

#8.其他注意事項
{ 1.在 Vue 開發 Web 應用的時候,通常使用 vue-router 來進行頁面路由;在 mpvue 小程序開發中,不能用這種方式,使用<a>標簽和小程序原生 API wx.navigateTo 做路由功能 2.請求后端數據,我們通常在 Web 開發中使用 axios 等 ajax 庫來實現;在小程序開發中也是不能用的,使用小程序的原生 API wx.request
}

#最后,思考
{ 1.怎么存放可全局訪問的變量? 2.頁面跳轉的時候,怎么傳遞參數到下一個頁面比較好? 3.頁面返回上一頁的時候,怎么傳遞當前頁的數據到上一頁? 4.多個頁面間需要同步數據,怎么做比較好?
}

直接在組件中通過 import 導入 store 所在的模塊文件,然后調用該 store 上的相關方法和屬性,比如 commit()、dispatch()等方法來操作 store 中的內容

#底部有彩蛋
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
v1
1
1
1
1
1
1

# 使用 vuex 狀態管理模式

第一種用法是將 store 綁定到需要訪問 store 內容的 Vue 實例上,然后通過該 Vue 實例下組件的 this.$store 來引用;或通過 mapState 等一系列映射函數將 store 中的 state、getters、mutations、actions 等映射成組件的計算屬性或 methods 方法來使用;

第二種用法是直接在組件中通過 import 導入 store 所在的模塊文件,然后調用該 store 上的相關方法和屬性,比如 commit()、dispatch()等方法來操作 store 中的內容。

#上面的這兩種方式在 mpvue 中也都是可用的。但是,由於 mpvue 不像 Vue Web 單頁應用那種單 Vue 實例的結構,而是采用了多 Vue 實例的結構(app 和各個頁面都會由單獨的 Vue 實例來管理),推薦采用上面所說的第二種用法,這種方式會更加靈活和簡單一些。

#代碼,先在 src 目錄下新建一個 stores 目錄,接着在 stores 目錄下新建一個名為 global-store.js 的文件:

import Vue from 'vue'
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: (state) => {
state.count += 1
},
decrement: (state) => {
state.count -= 1
}
}
});
在這個代碼中,我們新建了一個 Store 實例,管理了一個名為 count 的數字類型的狀態,並定義了 2 個 mutations 去操作(增減)這個狀態值。

接着,我們要在 2 個頁面中訪問這個 store。讓我們在 src/pages 目錄下編寫 2 個頁面:index 和 test1。

這是 pages/index/index.vue 的代碼內容:

<template>
<div class="container">
<div>計數結果:{{count}}</div>
<a href="/pages/test1/main" class="navlink">進入計數器頁面</a>
</div>
</template>

<script>
import globalStore from "../../stores/global-store";

export default {
computed: {
count() {
return globalStore.state.count;
}
}
};
</script>

<style scoped>
.navlink {
text-decoration: underline;
}
</style>

這是 pages/test1/index.vue 的代碼內容:

<template>
<div class="container btns">
<button class="calbtn" @click="hanleDecrement">-</button>
<span class="calnum">{{count}}</span>
<button class="calbtn" @click="hanleIncrement">+</button>
</div>
</template>

<script>
import globalStore from "../../stores/global-store";

export default {
computed: {
count() {
return globalStore.state.count;
}
},

methods: {
hanleIncrement() {
globalStore.commit("increment");
},

hanleDecrement() {
globalStore.commit("decrement");
}
}
};
</script>

<style scoped>
.btns {
display: flex;
align-items: center;
}
.calnum {
color: red;
font-size: 32px;
}
</style>

這樣,我們就有了 2 個使用了我們定義的 global-store 的頁面,這些頁面都會從 store 中獲取 count 狀態值並顯示;在 test1 頁面中,還會調用 increment 和 decrement 兩個 mutations 去更新 count 值。

運行小程序,可以看到初始進入 index 頁面時是這樣的,頁面上顯示的計數結果是 0:

index 頁面然后點擊“進入計數器頁面”進到 test1 頁面,並在這個頁面上點擊加減按鈕操作一下,當中顯示的 count 數會發生改變:

test1 頁面最后,點擊左上角返回按鈕返回 index 頁面,你將發現這個頁面上的計數結果也已經發生了改變,自動同步成前面操作后的結果了:8

#使用 Vuex 做頁面間的傳值和數據同步很簡單 #同樣可以在 src/stores 目錄下按需創建多個 store 模塊,獨立管理不同業務范圍的數據,並按需導入頁面組件使用

#vuex 官網https://vuex.vuejs.org/zh/

# 小程序/mpvue 中使用 flyio 發起網絡請求

# Fly.js 庫是一個基於 Promise 的、強大的、支持多種 JavaScript 運行時的 http 請求庫,支持請求/響應攔截器、自動轉化 JSON、請求轉發等功能
 
 
參考了 https://www.jianshu.com/p/579035fc9c18 && https://blog.csdn.net/sinat_36978723?t=1 兩位博主


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM