前段時間學習了Vue框架,因此在我學習程序中整理了一些關于Vue的一些需要注意的地方,在后面根據所開發的專案,我可能會持續更新這篇基于Vue的博客,歡迎交流
文章目錄
- 1.Vue中的mvvm
- 2. methods和computed
- 3. v-on的引數傳遞問題與常用的修飾符
- 3.1 引數傳遞問題
- 3.2 常用修飾符
- 5.v-if和v-show的區別
- 6.v-for時系結key與不系結key的區別
- 7. Vue中陣列方法中哪些是回應式的
- 8. v-model雙向系結使用
- 8.1 用于表單時
- 9. 為什么組件中data必須是一個函式型別
- 10.父子組件之間實作的復雜雙向系結
- 11.vue使用webpack時的注意事項
- 11.2 編譯vue檔案
- 12.Runtime-Compiler和Runtime-Only的區別
- 關于Render函式的使用:
- 13.vue-router懶加載
1.Vue中的mvvm
我們使用過Vue的人后都會清楚Vue是一種使用mvvm模式開發的框架,但是它的具體體現在哪里呢,

如上圖所示:
View層:就是我們常說的視圖層,也就時我們的BOM,主要用于給用戶展示資料
Model層:資料層,可能是我們給定的死資料,但在開發中大概率是從服務器端請求的資料
View-model層:視圖模型層,是View和Model溝通的橋梁,它主要實作了資料的系結和資料的動態監聽,實作了回應式資料化,
2. methods和computed
在vue的options選項中,除了method方法可以處理我們的邏輯以外,計算屬性也是可以操作相同的事情的,似乎他們很相似,其實他們是有區別的,所以這兩個方式有什么區別呢,
- 計算屬性不需要使用呼叫的形式的寫法,而methods方法必須使用
方法()呼叫的形式 - 計算屬性依賴data中的變化,如果data并沒有發生變化,則計算屬性則會取快取結果,也就是說計算屬性具有快取功能,
- method方法不論data中的值改不改變,都會重新呼叫,也就是呼叫多少次就實作多少次,因此比較浪費效率
3. v-on的引數傳遞問題與常用的修飾符
v-on經常用來處理一些事件監聽的操作,它的語法糖是@事件
3.1 引數傳遞問題
我們在使用v-on來處理事件時經常在事件中嵌入方法,這時會分三種情況,
- 不傳參時,可以不帶可以不帶括號,但是在方法實作時可加一個引數來表示當 前event,
<div class="box">
<button @click='btnclivk'></button>
</div>
btnclivk(e){
console.log(e);//當前event物件
}
- 傳普通引數時,就像通常使用函式一樣,但是需要注意的是,這里的引數要么是基本資料型別,要么就必須是data中的變數
- 在傳普通引數時還需要event引數,這時傳入
$event()固定寫法來表示當前event物件
3.2 常用修飾符
- v-on:事件.stop:阻止事件冒泡
- v-on:事件.prevent:阻止默認行為
- v-on:事件.{keycode}:等待指定鍵位觸發
- v-on:事件.once:只觸發一次
- v-on:事件.native:監聽組件跟元素的原生
5.v-if和v-show的區別
首先我們應該清楚v-if和v-show都是用來處理dom是否顯示出來的操作,因此我們在這里需要清楚他們有什么不同之處,
**v-if:**在使用v-if時通常時需要創建dom的,也就是說當值為false時,洗掉dom,當值為true時創建dom
**v-show:**在使用時通常時使用display:none的css樣式來處理是否可見的
使用常見:
當在界面中需要重復顯示和隱藏的操作時我們通常需要使用v-if,因為這樣更見的節省效率,
當只有一次切換時我么通常選擇v-if來進行操作,
6.v-for時系結key與不系結key的區別
首先想象一個場景,我們要將一個陣列顯示在li標簽上,這時會使用到v-for來對li標簽進行操作,但是當我有一個需求:你需要在陣列中間插入一個內容應該如何操作,
這時我們可能想著直接將內容插入陣列即可,但是你是否考慮到一個問題,在Vue的底層時如何實作的,
實際上Vue底層會使用虛擬DOM來實作這個操作,但是當我們插入在中間時,可能會出現以下這種情況:
除了前面相同的dom會復用以外,剩下的所有資料都要被重新渲染,
舉個例子,如果我們現在的陣列是[a,b,c,d,e],當我們現在在b后面加一個f,那么默認操作是將c—>f,d—>c,e—>d,最后插入e,這樣做感覺效率有所欠缺,如下圖所示:

因此官方建議我們使用系結key,key的值一般為是一個唯一標識(注意不能使用index:因為插入元素后index會改變,因此無意義),這樣一來diff演算法可以找到相同的復用dom進行渲染,也就是將我們有key的li一一對應起來
最后再將我們的待插入結點插入,這樣就省了不少的效率,

所以用一句話來概括,key的作用主要是為了高效的更新虛擬DOM,
7. Vue中陣列方法中哪些是回應式的
我們再使用Vue時感覺其很方便的一個主要原因就是它可以回應式重繪資料,
那么再我們使用陣列時,有哪些方式是資料回應式的呢,
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
Vue.set()
主要:直接通過陣列[下標值]是不能做到資料回應式的,
8. v-model雙向系結使用
8.1 用于表單時
v-model通常在表單中用來實作雙向系結,從而實作操作與資料實時更新,實作回應式,
也就是說當我們在表單中輸入資料時,實際上資料直接就發生了更改,
lizi :
<input type="text" v-model='message'>
<p>{{message}}</p>
以上例子就可以實作當我們輸入資料時,message就實時的發生了改變,對應的p標簽的內容也就發生了改變,
實際上v-model是以下兩個操作的語法糖:
- v-bind為value系結資料
- v-on:input 為表單系結觸發事件,從而為message傳值,
<input type="text" :value='message' @input='message=$event.target.value'>
<p>{{message}}</p>
其實除了在text上外,v-model還經常用在select、chacked、radio上,
修飾符:
這里主要介紹它的三個修飾符
- v-model.lazy:表示不實時更新資料,只有在用戶回車時或者input失焦時才更新資料
- v-model.number:在默認情況下v-model都是一個string型別的字串,這個修飾符可以使回傳一個數字型別
- v-model.trim:去空格
9. 為什么組件中data必須是一個函式型別
首先vue的組件大多是用來復用的,那么他每復用一次,就會使用我們的data屬性,如果這時我們data是一個物件時,那么當我們復用組件時則會出現一個問題,一個組件中資料變化,那么所有的組件中的資料都會變化,因此vue的底層在data屬性這里添加了這個設定,
當然在開發程序中也可能會遇到這個屬性,這個可以將物件暴露出去再引入,實作所有組件資料的一致性,
我們可以看一下一個很簡單的例子:
寫一個計數器的組件
Vue.component('mycom', {
template: '#mypom',
data() {
return {
message: 0
}
},
methods: {
add() {
this.message++
},
decre() {
this.message--
},
},
})
使用:
<div id="app">
<mycom></mycom>
<mycom></mycom>
<mycom></mycom>
<mycom></mycom>
</div>
這時我們會發現每個組件都是獨立的,這時因為,這就歸功于data屬性是一個函式,因此他們不會共同使用一個物件內的資料,
但是如果我們有這種一個動,全部動的需求時,也很容易,
var obj={
message: 0
}
Vue.component('mycom', {
template: '#mypom',
data() {
return obj
},
methods: {
add() {
this.message++
},
decre() {
this.message--
},
},
})
這就可以實作我們想要的效果,
10.父子組件之間實作的復雜雙向系結
一個需求:現在在組件中有兩個input,其中需要實作input的雙向系結(且改變父組件的data值),且輸出時第二個input的值時第二個值的100倍,
用到的技術點:父子組件通信,表單的雙向系結
值得一提的是當我們Vue官方不建議使用model時直接將props的值放在里面,因為這樣這里的值是從父組件傳遞而來,因此直接修改可能會導致紊亂,因此我們需要借助組件的data屬性來做值得系結;
至于另一個需求,改變data的屬性,那么我們可以使用父傳子的方法將組件的data傳給父組件,再去修改父組件data的值,這樣一來我們及修改了父組件的data,同時也就修改了子組件props的相關值,
最后的需求是100倍,這個也在我們的input事件觸發時監聽,然后計算,在通過emit傳遞即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<mycon :cnum1='num1' :cnum2='num2' @event1='event1' @event2='event2'></mycon>
</div>
<template id="cpm">
<div>
<p>props:{{cnum1}}</p>
<p>data:{{copycnum1}}</p>
<input type="text" name="" id="" :value='copycnum1' @input='docopycnum1'>
<p>props{{cnum2}}</p>
<p>data{{copycnum2}}</p>
<input type="text" name="" id="" :value='copycnum2' @input='docopycnum2'>
</div>
</template>
</body>
<script src="../vue.js"></script>
<script>
var cpm = {
template: '#cpm',
props: {
cnum1: Number,
cnum2: Number,
},
data() {
// 官方建議做法
return {
copycnum1: this.cnum1,
copycnum2: this.cnum2,
}
},
methods: {
docopycnum1(event) {
this.copycnum1 = event.target.value;
this.$emit('event1', this.copycnum1);
this.copycnum2=this.copycnum1*100
this.$emit('event2', this.copycnum2)
},
docopycnum2(event) {
this.copycnum2 = event.target.value;
this.$emit('event2', this.copycnum2)
this.copycnum1=this.copycnum2/100
this.$emit('event1', this.copycnum1)
}
},
}
new Vue({
el: '#app',
data: {
num1: 0,
num2: 0
},
components: {
mycon: cpm
},
methods: {
event1(data) {
this.num1 = parseFloat(data);
},
event2(data) {
this.num2 = parseFloat(data);
}
},
})
</script>
</html>
11.vue使用webpack時的注意事項
首先我們專案中需要有vue的環境,
npm安裝:
npm install vue --save
安裝以后,我們直接寫vue相關的代碼后進行編譯會發現有報錯:

這個錯誤的原因是因為vue在構建發布時有兩個版本,runtime-only和runtime-compiler,
**runtime-only:**該版本不能有任何的template
**runtime-compiler:**代碼里可以有template,因為有compiler可以編譯template
解決方案(在webpack組態檔中加入):
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
因為這個resolve時專門來處理路徑問題的,所以故名思意,我們也可以猜出來,這是改變了默認配置
11.2 編譯vue檔案
使用webpack中打包vue檔案時,我們需要安裝vue-loader插件和vue-template-compiler 插件
接著在組態檔中配置:
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
使用之后我們會發現會報錯,
報錯原因大概是:vueloader不能使用,缺少一個插件,
我們可以配置一個插件(不用安裝):
const VueLoaderPlugin = require('vue-loader/lib/plugin');
plugins: [
new VueLoaderPlugin(),
...
],
12.Runtime-Compiler和Runtime-Only的區別
當我們使用vue cli2來構建專案時通常會讓我們選擇vue的構建模式,我們創建兩個專案會發現src目錄下的main.js檔案按有所不同
Runtime-Compiler模式:
import App from './App';
new Vue({
el: '#app',
components: { App },
template: '<App/>',
});
Runtime-Only模式:
import App from './App';
new Vue({
el: '#app',
render:h=>h(app)
});
我們發現這兩個模式在Vue實體中的寫法有所不同,我們發現Runtime-Compiler模式時使用的時我們常規的注冊使用組件的方式,而Runtime-only是使用render函式進行渲染,那么這兩者有什么區別?
這是一張template在Vue中的渲染程序:

ast:template決議后的產物,抽象語法樹
render函式:ast被編譯就的產物,用于生成一個虛擬dom
virtual dom:虛擬dom
我們可以看出它大概需要這幾個程序:template->ast->render函式->虛擬dom->渲染到ui
然而我們使用第二種Runtime-Only是直接在render函式的結點開始往下操作的,
結論:Runtime-Only的效率要比Runtime-Compiler運行效率高,并且源代碼的量更少,打包后的體積更加輕量,
runtime-only: 將template在打包的時候,就已經編譯為 render函式
runtime-compiler: 在運行的時候,才去編譯 template因此我們更加推薦使用Runtime-Only模式來構建我們的專案,
關于Render函式的使用:
1.直接在render函式中給我們的回呼函式傳入我們的組件物件,
new Vue({
el: '#app',
// components: { App },
// template: '<App/>',
render:(e) => {
return e(App)
}
});
2.傳入基本的dom:
render:(e) => {
return e('div',{class:'box'},['web'])
}
其中第一個引數是dom元素,第二個引數是屬性值,第三個為data,
13.vue-router懶加載
? 關于路由的懶加載,官方給我們的解釋為:
當打包構建應用時,JavaScript 包會變得非常大,影響頁面加載,如果我們能把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應組件,這樣就更加高效了,
? 其實就是說我們的每一個路由對應的就是一個給用戶展示的頁面,然而按照常規的操作這些頁面最侄訓通過webpack打包為一個bundle.js的檔案,因此就造成了這個頁面十分的龐大,所在在請求的時候可能會花費一定的時間,給用戶造成不好的體驗,因此我們可以通過路由懶加載的方式來解決這個問題,也就是說不同的路由頁面打包成不同的js檔案,這樣就解決了服務器耗時的問題,
在我們未使用懶加載時,打包vue專案會生成三個檔案,一個是app的所有業務代碼,一個是組織管理模塊關系的代碼,還有一個就是專案引入第三方的代碼,
? 接著我們看一下實作懶加載的方式:有三種方式分別是結合異步組件的方式,AMD的方式,es6模塊化的方式
? 在ES6中, 我們可以有更加簡單的寫法來組織Vue異步組件和Webpack的代碼分割.所以我們就是用最簡單的方式:
component: () => import('../components/about.vue')
實體:
routes: [
{
path: '/',
redirect: '/home'
},
{
path: '/hello',
component: () =>import('../components/HelloWorld.vue')
},
{
path: '/home',
component: () => import('../components/home.vue')
},
{
path: '/about',
component: () => import('../components/about.vue')
},
{
path: '/person/:userid',
component: () => import('../components/person.vue')
}
],
我們發現每個路由界面都有一個js檔案,這樣一來就可以做到我們按需加載的要求,減輕了服務器的壓力
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/278487.html
標籤:其他
上一篇:7種經常使用的Vue.js模式和36個實用Vue開發技巧,你知道多少?
下一篇:十二、表單驗證技術
