前言
以前自己只練習過開發(fā)些原生微信小程序,改用uni框架試試,簡單記錄下流程以及遇到的些問題。(記的東西有點雜,自用 ??看起來繁雜請見諒)
一、大體流程
1.uni-app項目搭建流程:
(1)先全局安裝
npm install -g @vue/cli
(只需要安裝一次,安裝過后就不用安裝了)
PS: 直接npm install -g@vue/cli 安裝 可能會報錯 問題其實不是webpack的問題。 把nodeJS的版本切換到12或者更低,就OK了.
- 卸載vuecli5.0版本: npm remove -g @vue/cli
- 安裝vue4.5.15版本: npm install -g @vue/cli@4.5.15
(2)創(chuàng)建項目
vue create -p dcloudio/uni-preset-vue my-project
(如果已有項目,cd后直接 npm install )
PS :npm WARN config global --global
, --local
are deprecated. Use `–location
解決方案:
- 找到目錄:打開nodejs,并打開要修改的2個配置文件(npm.cmd 和 npm)
- 進行修改:將prefix -g替換為prefix --location=global
- 檢驗問題:輸入npm-v
(3)進入項目里
cd my-project
(4) 需要的話 先安裝sass依賴
npm install sass-loader node-sass
安裝后style標簽中加入屬性 < style lang = “scss” >
(5)運行項目
npm run dev:mp-weixin
(6)打開微信開發(fā)者工具 導入項目myproject—>dist—>dev—>mp-weixin
2.團隊開發(fā)流程
(1)打開DCH,建立個人分支
(2)將項目導入到本地
(3)建立連接 打開VScode編譯 同步個人分支
(4)提交代碼后,打開Git Extensions 進行Push
二、遇到的些問題
1.插件的使用
①使用uni原生ui插件:
(1)項目搭建完,先安裝sass 及 sass-loader
- npm i sass -D
- npm i sass-loader@10.1.1 -D
(2)安裝uni-ui
npm install @dcloudio/uni-ui
(3)在script中引用和注冊組件
<script>
import {uniBadge} from '@dcloudio/uni-ui'
export default {
components: {uniBadge}
}
</script>
(現(xiàn)在更多用uni_modules直接導入 會更加方便,詳情見 uniapp:uni_modules組件開發(fā)與發(fā)布)
(4)在 template 中使用組件:
<template>
<uni-badge text="1"></uni-badge>
<uni-badge text="2" type="success" @click="bindClick"></uni-badge>
<uni-badge text="3" type="primary" :inverted="true"></uni-badge>
</template>
②使用SegmentedControl分段器
(1)SegmentedControl分段器也是Cloud團隊開發(fā)的,先進行安裝uni-ui(見①)
(2)然后打開插件市場,搜索你需要的插件,找到插件文檔說明,比如uni-segmented-control插件文檔
(3)遷移代碼后,記得引用和注冊組件。
代碼片段示例:
<template>
<view>
<uni-segmented-control :current="current" :values="items" @clickItem="onClickItem" styleType="button" activeColor="#4cd964"></uni-segmented-control>
<view class="content">
<view v-show="current === 0">
選項卡1的內(nèi)容
</view>
<view v-show="current === 1">
選項卡2的內(nèi)容
</view>
<view v-show="current === 2">
選項卡3的內(nèi)容
</view>
</view>
</view>
</template>
<script>
//引用和注冊組件
import { uniSegmentedControl } from '@dcloudio/uni-ui'
export default {
components: { uniSegmentedControl },
data() {
return {
items: ['選項1', '選項2', '選項3'],
current: 0
};
},
methods: {
onClickItem(e) {
if (this.current != e.currentIndex) {
this.current = e.currentIndex;
}
}
}
}
</script>
③使用uViewUI
官方文檔
實例項目
1.npm安裝
- npm init -y //根目錄沒有package.json時執(zhí)行
- npm install uview-ui //安裝
- npm update uview-ui //更新
2.main.js引入uView庫
import uView from 'uview-ui' ;
Vue.use(uView);
3.安裝sass
4.App.vue引入樣式
<style lang = "scss" >
@import "uview-ui/index.scss";
</style>
5.uni.scss引入全局scss變量文件
@import "uview-ui/theme.scss";
6.page.json配置easycom規(guī)則(按需引入)
//page.json
{
"easycom":{
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
"pages": [
//......
]
}
2.組件之間的傳參
①父子組件間傳參
1.父向子傳遞參數(shù):
父傳子,通過屬性方法:
2.子向父傳遞參數(shù):
子傳父,子組件通過觸發(fā)事件傳遞,父組件通過監(jiān)聽事件接收
先在子組件內(nèi)部綁定事件:
在父組件監(jiān)聽:
②VueX
實際上,在組件的mounted鉤子函數(shù)中就能進行數(shù)據(jù)的請求,父子組件之間,非父子組件之間進行傳值也有一些方法,小型的項目也許這么做沒事沒問題,但是如果是進行大型項目,非父子之間傳值,父子之間傳值會出現(xiàn)混亂復雜的情況,如果使用vuex不止能把數(shù)據(jù)放在全局,組件無論在哪都能反問獲取到,并且線路清晰,有利于維護。
vuex是基于vue框架的一個狀態(tài)管理庫。可以管理復雜應用的數(shù)據(jù)狀態(tài),比如兄弟組件的通信、多層嵌套的組件的傳值等等。
vuex有這么幾個核心概念——State、Getter、Mutation、Action、Module。
客戶端要請求數(shù)據(jù) ==>> 對接actions,在actions中進行axios請求 ==>> 請求過來的數(shù)據(jù)給mutations進行數(shù)據(jù)存儲 ==>> 數(shù)據(jù)存在state中 ==>> getters將state中的數(shù)據(jù)進行返回 ==>> 客戶端對接getters接收數(shù)據(jù):
1.配置步驟
npm install vuex --save 先安裝依賴
1、在項目根目錄中創(chuàng)建 store 文件夾,專門用來存放 vuex 相關(guān)的模塊
2、在 store 目錄上鼠標右鍵,選擇 新建 -> js文件,新建 store.js 文件
3、在 store.js 中按照如下 4 個步驟初始化 Store 的實例對象:
// 1. 導入 Vue 和 Vuex
import Vue from 'vue'
import Vuex from 'vuex'
// 2. 將 Vuex 安裝為 Vue 的插件
Vue.use(Vuex)
// 3. 創(chuàng)建 Store 的實例對象
const store = new Vuex.Store({
// TODO:掛載 store 模塊
modules: {},
//State:{},Getter:{},Mutation:{},Action:{}
})
// 4. 向外共享 Store 的實例對象
export default store
4、在 main.js 中導入 store 實例對象并掛載到 Vue 的實例上:
// 1. 導入 store 的實例對象
import store from './store/store.js'
// 省略其它代碼...
const app = new Vue({
...App,
// 2. 將 store 掛載到 Vue 實例上
store,
})
app.$mount()
2.基本用法
state
用來存儲組件間共享的值
store.js定義:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 10,
}
})
export default store
組件:
<template>
<block>
<view>當前最新的count值為: {{count}} </view>
</block>
</template>
<script>
import { mapState } from 'vuex';
export default {
data() {
return {
}
},
computed: {
...mapState(['count']),
},
}
</script>
然后主頁面正常引入插件就可以了
mutations
只有 mutations 中定義的函數(shù),才有權(quán)力修改state值
store.js定義:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 10,
},
mutations: {
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
})
export default store
組件:
<template>
<block>
<view>當前最新的count值為: {{count}} </view>
<button @click="btnHandler1">-1</button>
<!-- <button @click="btnHandler2">-N</button> -->
<button @click="subN(4)">-N</button> //可以直接引方法函數(shù)名,無需綁點擊事件
</block>
</template>
<script>
import { mapState,mapMutations } from 'vuex';
export default {
data() {
return {
}
},
computed: {
...mapState(['count']),
},
methods: {
...mapMutations(['sub','subN']),
btnHandler1(){
this.sub()
},
// btnHandler2(){
// this.subN(5)
// },
},
}
</script>
actions
異步操作變更數(shù)據(jù)必須通過Actions,而不能使用Mutations
必須通過 context.commit() 觸發(fā)某個mutation才行
store.js定義:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 10,
},
mutations: {
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
actions: {
subAsync(context){
setTimeout(() => {
context.commit('sub')
},1000) //做個延時效果
}
},
})
export default store
組件:
<template>
<block>
<view>當前最新的count值為: {{count}} </view>
<button @click="sub">-1</button>
<button @click="subN(4)">-N</button>
<button @click="subAsync">-1 Async</button>
</block>
</template>
<script>
import { mapState,mapMutations,mapActions} from 'vuex';
export default {
data() {
return {
}
},
computed: {
...mapState(['count']),
},
methods: {
...mapMutations(['sub','subN']),
...mapActions(['subAsync']),
},
}
</script>
getters
用于對Store中的數(shù)據(jù)進行加工處理形成新的數(shù)據(jù),不修改state
store.js定義:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 10,
},
mutations: {
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
actions: {
subAsync(context){
setTimeout(() => {
context.commit('sub')
},1000)
}
},
getters:{
showNum: state => {
return '當前最新數(shù)量是【'+ state.count + '】'
}
}
})
export default store
組件:
<template>
<block>
<view>當前最新的count值為: {{count}} </view>
<button @click="sub">-1</button>
<button @click="subN(4)">-N</button>
<button @click="subAsync">-1 Async</button>
<view>{{showNum}} </view>
</block>
</template>
<script>
import { mapState,mapMutations,mapActions,mapGetters } from 'vuex';
export default {
data() {
return {
}
},
computed: {
...mapState(['count']),
...mapGetters(['showNum'])
},
methods: {
...mapMutations(['sub','subN']),
...mapActions(['subAsync']),
},
}
</script>
③Mixins
-
與公共組件的區(qū)別
組件:在父組件中引入組件,相當于在父組件中給出一片獨立的空間供子組件使用,然后根據(jù)props來傳值,但本質(zhì)上兩者是相對獨立的。
Mixins:則是在引入組件之后與組件中的對象和方法進行合并,相當于擴展了父組件的對象與方法,可以理解為形成了一個新的組件。 -
與vuex的區(qū)別
vuex:用來做狀態(tài)管理的,里面定義的變量在每個組件中均可以使用和修改,在任一組件中修改此變量的值之后,其他組件中此變量的值也會隨之修改。
Mixins:可以定義共用的變量,在每個組件中使用,引入組件中之后,各個變量是相互獨立的,值的修改在組件中不會相互影響。 -
實例文檔
3.session_key
功能說明 微信客戶端通過wx.getUserInfo()獲取用戶的信息
后臺有時候也需要獲取微信客戶端的用戶信息,因此,就需要利用session_key這個秘鑰來從微信平臺中獲取 [微信官方的鏈接]
-------> session_key 有什么用?
服務端給你的數(shù)據(jù)是加密的,如果你想解密就需要就需要sesison_key
--------> 怎么獲取session_key ?
客戶端通過 wx.login方法獲取一個code(5 分鐘內(nèi)有效),把code 發(fā)送給自己的服務器,服務器通過另外的接口獲取session-key
---------->如果我存儲ssessiion-key 在自己的服務器,每次解析數(shù)據(jù)的時候就可以直接使用啦?
并不是,session-key 會過期。
----------> 那么我第一次登錄的時候解析完數(shù)據(jù),保存到服務器里,以后就不需要反復獲取用戶數(shù)據(jù),獲取sessionkey 并且解析數(shù)據(jù)啦?
可以,但是有個缺點,你保存的信息,是用戶第一次登錄時候的信息,如果用戶修改了頭像之類的,你數(shù)據(jù)庫的信息不能夠和微信的保持同步。
----------> 我想要自己的數(shù)據(jù)是最新的怎么辦?
那么就每次進入小程序的時候調(diào)用登錄接口,獲取新的用戶數(shù)據(jù),獲取sessonkey, 解析數(shù)據(jù),然后展示數(shù)據(jù)。
----------->每次都要調(diào)用登錄接口?
好像是這樣,
---------->那么后臺也要每次都獲取sessionkey嗎
不需要,你可以在前端通過checksessionkey 來檢查sessionkey 是不是已經(jīng)過期了,如果沒有過期,那么就不需要重新獲取。
---------> 每次都登錄是不是有點麻煩?
我覺得也是,所以直接獲取一次信息就好了,本地存儲一個token ,除非用戶刪除小程序,不然的話,根本不需要登錄。
微信登錄過程
1.wx.login() 這個方法會返回一個code
2.后臺根據(jù) code + appid + appsecret 這個三個參數(shù)完成登錄的認證,得到微信客戶端的openid + session_key
①wx.checkSession()
有時候,我們會因為session_key不正確而導致解密或者校驗簽名失敗。有幾方面的原因:
1、因為wx.login()被調(diào)用時,用戶的session_key會被更新導致就session_key失效。所以,在調(diào)用wx.login()的時候應該要明確需要登錄之后再調(diào)用。
2、另外,微信不會把session_key的有效期告訴我們,用戶越頻繁使用微信,session_key的有效期就更長。
因為,就需要調(diào)用wx.checkSession()來校驗當前用戶的session_key是否有效。
onLoad: function () {
wx.checkSession({
success: function(res){
console.log("處于登錄態(tài)");
},
fail: function(res){
console.log("需要重新登錄");
wx.login({})
}
})
}
4.優(yōu)化項目代碼
①分包
請點擊該鏈接,這位博主歸納的很好,如果想加快小程序啟動速度,可在pages.json里配置preloadrule
5.實現(xiàn)些功能
①聊天界面
鏈接1
鏈接2
②平臺環(huán)境判斷
判斷環(huán)境:
if(process.env.NODE_ENV === 'development'){
console.log('開發(fā)環(huán)境')
}else{
console.log('生產(chǎn)環(huán)境')
}
判斷平臺:
switch(uni.getSystemInfoSync().platform){
case 'android' :
console.log('運行在Android上')
break;
case 'ios' :
console.log('運行在IOS上')
break;
default :
console.log('運行在開發(fā)者工具上')
break;
}
③實現(xiàn)滑動滾動
<template>
<scroll-view class="scroll" scroll-x>//1
<view class = "group" >
<view class = "item">測試數(shù)據(jù)</view>
<view class = "item">測試數(shù)據(jù)</view>
...
</view>
</scroll-view>
</template>
<style lang = "scss">
.scroll{
border:1px solid red;
box-sizing: border-box; //2
.group{
white-space: nowrap; //3
.item{
width: 220rpx;
height: 220rpx;
background: bule;
display: inline-block; //4
margin-right: 10rpx;
}
}
}
}
</style>
概念文檔:1 2 3 4
④實現(xiàn)緩存列表數(shù)據(jù)
頁面的緩存,我們需要用到vue的內(nèi)置組件keep-alive,來緩存列表頁面,同時配合路由選項來更改頁面的數(shù)據(jù)。
從A頁面跳轉(zhuǎn)到B頁面,返回A頁面時 不會重新加載A頁面數(shù)據(jù)
1.在路由選項中,router文件里配置meta屬性
//router index.js path: '/pageA',
meta: {
keepAlive:true //添加作為標志符,表明該頁面需要保留狀態(tài)
// isBack: false //標示頁面是否是從articleDetail頁面返回的
}
2.設(shè)置beforeRouteEnter判斷從哪跳轉(zhuǎn)的 如果是從詳情頁跳轉(zhuǎn)的,則將當前路由對象的meta.isBack 設(shè)置為true,否則設(shè)為false
export default {
data() {
},
// beforeRouteEnter(to, from, next) {
// if (from.path == "/pageB") {
// to.meta.isBack = true;
// } else {
// to.meta.isBack = false;
// }
// next();
// },
beforeRouteLeave(to,from,next){
to.meta.keepAlive = true
next(0)
},
}
3.為了在其他頁面進入時,更新頁面中的列表數(shù)據(jù),我們將在activated鉤子函數(shù)中掛載頁面初次進入時的請求數(shù)據(jù)
// activated() {
// if (!this.$route.meta.isBack) {
// this.List = [];
// this.pageNum = 1;
// this.getList();
// }
// this.$route.meta.isBack = false;
// },
4.記得在App.vue聲明一下
<keep-alive include="pageA">
<router-view/>
</keep-alive>
⑤點擊按鈕 增添DIV
之前用innerhtml轉(zhuǎn)義 那個辦法挺笨的 有的判斷無法識別 改為這種
⑥點擊按鈕 刪除DIV
刪除我參考的這個
⑦調(diào)用接口,傳值返回數(shù)據(jù)
傳入v.fourMCode返回后,賦值給res,再加入要使用的對象數(shù)組
let res = await this.$axiox.get('/api/ProMats/query/fourMCode?fourMCode=' + v.fourMCode, null, false)
console.log(res.data)
this.fourmList[i] = res.data
let res = await this.$axiox.post('/api/Content/checkDocumentVersion', this.fourMCodeList[i].fourthMCodeDocuments, 0)
console.log('檢查版本號', res.data)
如果是接手別人的項目。格式一般都看axios.js里是如何聲明的
參考這篇文檔
⑧帶參跳轉(zhuǎn)頁面
傳值:
window.location.href = 'Url?id=' + 值 //在當前頁面刷新
window.open('Url?id=' + 值) //另開新頁面
接收:
if(this.$commonJs.getHrefName('id')){
接收參數(shù) = this.$commonJs.getHrefName('id') // 接收傳來的值
}
調(diào)用common.js文件里的一個方法
// 獲取指定querystring的值
getHrefName(name) {
let href = window.location.href.split('?')[1] || ''
let hrefArray = href.split('&')
for (let i = 0; i < hrefArray.length; i++) {
if (name === hrefArray[i].split('=')[0]) {
return hrefArray[i].split('=')[1]
}
}
},
⑨Vue 實例重新渲染
$forceUpdate很好用,注意它僅僅影響實例本身和插入插槽內(nèi)容的子組件,而不是所有子組件。
this.$forceUpdate()
好點的辦法用$set:接收3個參數(shù),參數(shù)1:參數(shù)是需要更新的數(shù)組或?qū)ο?,參?shù)2:是數(shù)組的下標或者對象的屬性名,參數(shù)3:是更新的內(nèi)容
- $set用于更新數(shù)組:
let arr = ["星期一","星期二","星期日"]
this.$set(arr,2,"星期三") //第一個參數(shù)是數(shù)組,第二個參數(shù)是下標索引,第三個參數(shù)是新的內(nèi)容
//更新之后的arr是["星期一","星期二","星期三"]
- $set用于更新對象:
//對象的屬性sex的值更新為"男"
let obj = {name:"六四",age:18,sex:"女"}
this.$set(obj,"sex","男") //第一個參數(shù)是對象,第二個參數(shù)是更新的屬性名稱,第三個參數(shù)是新的內(nèi)容
//更新之后的obj是 {name:"六四",age:18,sex:"男"}
⑩ios端首次進入單次刷新頁面
記錄個小demo
if(/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){
if (!window.sessionStorage.getItem('isReloaded')) {
window.sessionStorage.setItem('isReloaded', true)
window.location.reload()
}else {
window.sessionStorage.removeItem('isReloaded')
}
}
?截取后端str字段
1.splice改變原數(shù)組,slice不改變原數(shù)組,一般截取后端的數(shù)據(jù)用slice方法
2.split() 方法用于把一個字符串分割成字符串數(shù)組。str.split(separator,limit) separator:從該參數(shù)指定的地方分割 string Object;limit:限制長度,可不傳。
str=‘How are you doing today’
1.截取str前十位
str.slice(0,10) //How are yo
2.截取str后十位
str.slice(-10) //oing today
3.分割str取值文章來源:http://www.zghlxwxcb.cn/news/detail-492281.html
str.split('you')[0]; //How are
str.split('you')[1]; //doing today
?處理移動端底部小黑條問題
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
?原型鏈
每個JavaScript對象都有一個指向其原型對象的引用,這個引用保存在對象的__proto__屬性中。如果在對象上訪問一個屬性或方法,而該對象本身沒有定義這個屬性或方法,JavaScript會沿著原型鏈向上查找,直到找到對象的原型對象,或者一直到達Object.prototype為止。這樣,對象可以繼承原型對象的屬性和方法。
__ proto__ = Vue.prototype文章來源地址http://www.zghlxwxcb.cn/news/detail-492281.html
- __proto__屬性:
__proto__是每個JavaScript對象都擁有的屬性,它指向?qū)ο蟮脑蛯ο?。通過__proto__屬性,可以訪問和修改對象的原型鏈。雖然它在一些現(xiàn)代JavaScript環(huán)境中被標記為不推薦使用,但它仍然是理解原型鏈機制的關(guān)鍵部分。 - Vue.prototype:
Vue.prototype是Vue.js框架中的一個重要概念。在Vue.js中,每個Vue實例都通過原型鏈繼承了一個共享的原型對象,該原型對象存儲了Vue.js的核心功能和方法,如 d a t a 、 data、 data、props、$watch等。這意味著你可以在所有Vue實例中共享這些功能。通常,開發(fā)者可以通過Vue.prototype來自定義或擴展Vue實例的原型,以添加自定義方法或?qū)傩浴_@是Vue.js實現(xiàn)組件化和擴展的重要機制之一。
到了這里,關(guān)于【用vue開發(fā)微信小程序】(uni-app)(自用,不推薦參考)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!