介紹:Vue起初是一個構(gòu)建數(shù)據(jù)驅(qū)動的web界面的庫诡挂,通過簡單的API提供高效的數(shù)據(jù)綁定和靈活的組件系統(tǒng),但隨著vue生態(tài)圈的發(fā)展临谱,如vue-router璃俗,vue-resource等的推出,vue已經(jīng)算得上是個輕量級的MVVM框架了悉默,官方定義vue是一套用于構(gòu)建用戶界面的漸進(jìn)式框架城豁。相較于Angular和React框架,vue的的學(xué)習(xí)曲線更平穩(wěn)抄课,這點也是我選擇Vue入門的原因唱星。
如何安裝?
- 直接HTML引入 script
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
- vue cli方式
$ npm install vue
Vue的核心思想
- 數(shù)據(jù)驅(qū)動
DOM是數(shù)據(jù)的一種自然映射跟磨,手動操作DOM是一件非常繁索且容易出錯的事情间聊,而使用vue.js后,就省去了手動操作DOM的步驟抵拘,在Vue.js里我們只需要操作數(shù)據(jù)哎榴,vue會通過Directives指令去修改對應(yīng)的DOM,從而實現(xiàn)數(shù)據(jù)驅(qū)動。
- 組件化
組件化的目的是擴(kuò)展HTML元素叹话,封裝可重用代碼
通過上圖偷遗,我們可以粗略理解為一個簡單的vue應(yīng)用大概先分兩部分:Vue實例、 HTML
第一部分 : vue實例
每個 Vue 應(yīng)用都是通過創(chuàng)建一個新的 Vue 實例開始驼壶,語法如下:
var vm = new Vue({
// 選項
})
構(gòu)造器的常用參數(shù)屬性包含:el
氏豌、data
、methods
热凹、computed
泵喘、watch
、生命周期鉤子
等般妙,具體應(yīng)用如下:
-
el
:提供一個在頁面上已存在的 DOM 元素作為 Vue 實例的掛載目標(biāo)纪铺,在vue單文件情況下不需要該屬性
#掛載到id為app的DOM節(jié)點上
el: '#app'
-
data
: 用于定義數(shù)據(jù)屬性,當(dāng) Vue 實例被創(chuàng)建時碟渺,它向 Vue 的響應(yīng)式系統(tǒng)加入了 data 對象中所有的屬性鲜锚。當(dāng)這些屬性的值變化時,HTML 視圖將也會產(chǎn)生相應(yīng)的變化苫拍。
# 實例創(chuàng)建之后,可通過 vm.$data 訪問原始數(shù)據(jù)對象骏令。Vue 實例也代理了 data 對象上所有的屬性垄提,因此訪問 vm.a 等價于訪問 vm.$data.a榔袋。
data: {
newTodoText: '',
visitCount: 0,
hideCompletedTodos: false,
todos: [],
error: null
}
-
methods
:用于定義的函數(shù)铡俐,通過 return 來返回函數(shù)值。
// 在組件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
-
computed
用于計算屬性审丘,當(dāng)模板中的邏輯復(fù)雜時聪黎,代碼非常難以看懂理解备恤,可考慮把邏輯寫在computed
中露泊,我們用 methods 替代 computed惭笑,效果一樣,但 computed 基于它的依賴緩存捺宗,只有相關(guān)依賴發(fā)生改變時才會重新取值蚜厉。而使用 methods 畜眨,在重新渲染的時候康聂,函數(shù)總會重新調(diào)用執(zhí)行恬汁∶ゲ啵可以說 computed 性能會更好甘苍,除非你不希望緩存。
computed: {
// 計算屬性的 getter
reversedMessage: function () {
// `this` 指向 vue 實例
return this.message.split('').reverse().join('')
}
}
-
watch
監(jiān)聽屬性來響應(yīng)數(shù)據(jù)的變化看彼,當(dāng)我們再輸入框輸入數(shù)據(jù)時靖榕,watch 會實時監(jiān)聽數(shù)據(jù)變化并改變自身的值茁计。
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
- vue實例還有一系列的生命周期鉤子星压,給了用戶在不同階段添加自己的代碼的機(jī)會娜膘。
-
beforeCreate
在實例初始化之后調(diào)用 -
created
在實例創(chuàng)建完成后被立即調(diào)用 -
beforemount
在掛載開始之前被調(diào)用 -
mounted
實例被掛載后調(diào)用 -
beforeupdate
數(shù)據(jù)更新時調(diào)用 -
updated
由于數(shù)據(jù)更改導(dǎo)致的虛擬 DOM 重新渲染和打補(bǔ)丁竣贪,在這之后會調(diào)用該鉤子 -
beforeDesgroy
實例銷毀之前調(diào)用 -
destroyed
實例銷毀后調(diào)用
-
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vue 實例
console.log('a is: ' + this.a)
},
beforeCreate: function () {
console.log('beforeCreate')
}
})
備注:
- 不要在選項屬性或回調(diào)上使用箭頭函數(shù)演怎,比如
created: () => console.log(this.a)
爷耀,因為箭頭函數(shù)并沒有this
- 當(dāng)這些數(shù)據(jù)改變時畏纲,視圖會進(jìn)行重渲染。但只有當(dāng)實例被創(chuàng)建時就已經(jīng)存在于 data 中的屬性才是響應(yīng)式的艘蹋;
- Vue實例針對數(shù)據(jù)女阀、DOM浸策、資源庸汗、組合等都有非常多靈活的屬性蚯舱,具體可查看官方API
第二部分 : HTML
vue實例承載了數(shù)據(jù)和邏輯相關(guān)的內(nèi)容枉昏,那么HTML就是處理我們view相關(guān)內(nèi)容了兄裂,Vue.js 使用了基于 HTML 的模板語法晰奖,允許開發(fā)者聲明式地將 DOM 綁定至底層 Vue 實例的數(shù)據(jù)腥泥。
插值表達(dá)式
數(shù)據(jù)綁定最常見的形式就是使用“Mustache”語法 (雙大括號)
# 基本形式 道川,無論何時冒萄,綁定的數(shù)據(jù)對象上 value 屬性發(fā)生了改變尊流,插值處的內(nèi)容都會更新
{{ value }}
# 只需渲染一次數(shù)據(jù)
{{ *value }}
#可放在HTML標(biāo)簽內(nèi)
<li data-id='{{id}}'></li>
# 表達(dá)式
{{ number / 100 }}
{{ true ? 1 : 0 }}
{{ example.split(",") }}
# Q录肌迎献!錯誤示例(語句并非表達(dá)式吁恍,條件控件語句也是不支持的)
{{var logo = 'DDEF'}}
{{if (true) return 'DDEF'}}
# 過濾器:
{{ date | formateDate }}
{{ example | toUpperCase}}
指令
指令 (Directives) 是帶有 v- 前綴的特殊 attribute冀瓦。指令的職責(zé)是當(dāng)表達(dá)式的值改變時翼闽,將其產(chǎn)生的連帶影響感局,響應(yīng)式地作用于 DOM。包含v-text
玄叠、v-html
读恃、v-show
寺惫、v-if
西雀、v-else
艇肴、v-else-if
再悼、v-for
冲九、v-on
莺奸、v-bind
灭贷、v-model
氧腰、v-slot
、v-pre
箩帚、v-cloak
、v-once
是嗜,在實際開發(fā)中應(yīng)用非常頻繁鹅搪,下面我們來詳細(xì)聊聊它們的用法遭铺。
v-bind
: 動態(tài)地綁定一個或多個特性魂挂,或一個組件 prop 到表達(dá)式坠非。
<!-- 完整語法 -->
<a v-bind:href="url"></a>
<!-- 縮寫 -->
<a :href="url"></a>
<!-- 內(nèi)聯(lián)字符串拼接 -->
<img :src="'/path/to/images/' + fileName">
<!-- 可用于綁定元素 attribute炎码,響應(yīng)地更新 HTML 屬性:-->
<div v-bind:id="dynamicId"></div>
<div v-bind:id="'list-' + id"></div>
<a v-bind:href="url">8891汽車</a>
<!-- 也可以用于綁定樣式:-->
<div v-bind:class="{ active: isActive }"></div>
<div v-bind:class="[ activeClass, errorClass ]"></div>
<div v-bind:class="[ errorClass ,isActive ? activeClass : '' ]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
<!-- style 綁定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
<!-- 綁定一個有屬性的對象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
<!--修飾符-->
<svg :view-box.camel="viewBox"></svg>
<!-- 通過 prop 修飾符綁定 DOM 屬性 -->
<div v-bind:text-content.prop="text"></div>
<!--.sync修飾符會擴(kuò)展成一個更新父組件綁定值的 v-on 偵聽器辅肾。-->
<text-document v-bind:title.sync="doc.title"></text-document>
v-show
根據(jù)表達(dá)式之真假值矫钓,切換元素的 display CSS 屬性
<!--根據(jù)表達(dá)式的值來顯示或隱藏HTML元素-->
<!--元素始終被編譯新娜,只是簡單地基于CSS切換概龄,相比v-if有更高的初始渲染消耗-->
<h1 v-show="ok">Hello!</h1>
v-if
條件判斷私杜,根據(jù)表達(dá)式的值在DOM中生成或移除一個元素
<!--v-if 條件語句-->
<p v-if="seen">現(xiàn)在你看到我了</p>
<!--v-else-->
<div v-if="Math.random() > 0.5"> Now you see me </div>
<div v-else> Now you don't </div>
<!--v-else-if-->
<div v-if="type === 'A'"> A </div>
<div v-else-if="type === 'B'"> B </div>
<div v-else-if="type === 'C'"> C </div>
<div v-else> Not A/B/C </div>
<!-- v-if 是惰性的,在條件第一次變?yōu)檎鏁r才開始局部編譯铝耻,否則什么都不做 . 相比v-show有更高的切換消耗 -->
v-for
循環(huán)語句 :
<!--遍歷數(shù)組瓢捉,其中 items 是源數(shù)據(jù)數(shù)組泡态,而 item 則是被迭代的數(shù)組元素的別名-->
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
<!-- 可選的第二參數(shù)某弦,索引-->
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
<!--遍歷對象-->
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
<!--可選的第二參數(shù)刀崖,鍵名-->
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
<!--可選的第三參數(shù)亮钦,索引-->
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
<!--為了給 Vue 一個提示蜂莉,以便它能跟蹤每個節(jié)點的身份映穗,從而重用和重新排序現(xiàn)有元素蚁滋,需為每項提供一個唯一 key 屬性-->
<div v-for="item in items" v-bind:key="item.id">
{{ item.message }}
</div>
<!--v-for里還可以使用值范圍-->
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
#VUE實例部分
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
],
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
備注:當(dāng)數(shù)組出現(xiàn)變動時睦霎,Vue是如何檢測呢副女?Vue 將被偵聽的數(shù)組的變異方法進(jìn)行了封裝碑幅,它們能觸發(fā)實圖更新沟涨。所以建議盡量避免直接設(shè)置數(shù)據(jù)綁定的數(shù)組元素拷窜,因為這些變化不會被vue.js檢測到篮昧,這些被封裝過的方法包括:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
相比之下懊昨,也有非變異 (non-mutating method) 方法酵颁,它們不會改變原始數(shù)組躏惋,而總是返回一個新數(shù)組簿姨。
- filter()
- concat()
- slice()
v-on
: 用于監(jiān)聽 DOM 事件准潭,并在觸發(fā)時運(yùn)行一些 JavaScript 代碼
<!-- `greet` 是在vue實例中定義的方法名 -->
<div id="example-2">
<button v-on:click="greet">Greet</button>
</div>
<!--內(nèi)聯(lián)處理器的方法-->
<div id="example-3">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
</div>
<!--事件修飾符-->
<!-- 阻止單擊事件繼續(xù)傳播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯(lián) -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>
<!-- 點擊事件將只會觸發(fā)一次 -->
<a v-on:click.once="doThis"></a>
<!-- 按鍵修飾符 -->
<!-- 按鍵修飾符刑然,只有在 `key` 是 `Enter` 時調(diào)用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
<input v-on:keyup.13="submit">
Vue.js 為 v-on 提供了事件修飾符泼掠。之前提過,修飾符是由點開頭的指令后綴來表示的。
- .stop
- .prevent
- .capture
- .self
- .once
- .passive
為了在必要的情況下支持舊瀏覽器叹谁,Vue 提供了絕大多數(shù)常用的按鍵碼的別名:
- .enter
- .tab
- .delete (捕獲“刪除”和“退格”鍵)
- .esc
- .space
- .up
- .down
- .left
- .right
v-model
: 用來在 input焰檩、select析苫、textarea衩侥、checkbox茫死、radio 等表單控件元素上創(chuàng)建雙向數(shù)據(jù)綁定履羞,根據(jù)表單上的值爱榔,自動更新綁定的元素的值详幽。
<!--指令用來在 input妒潭、select雳灾、textarea谎亩、checkbox匈庭、radio 等表單控件元素上創(chuàng)建雙向數(shù)據(jù)綁定阱持,根據(jù)表單上的值鸽扁,自動更新綁定的元素的值桶现。-->
<input v-model="message" >
<textarea v-model="message" placeholder="add multiple lines"></textarea>
<!--單復(fù)選框-->
<input type="checkbox" id="checkbox" v-model="checked">
<!--多復(fù)選框 骡和,綁定到數(shù)組 data: {checkedNames: []}-->
<div id='example-3'>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
</div>
<!--單選框,綁定到 data: {picked: ''}-->
<div id="example-4">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
</div>
<!--選擇框东囚,綁定到 data: {selected: ''}-->
<div id="example-5">
<select v-model="selected">
<option disabled value="">請選擇</option>
<option>A</option>
<option>B</option>
</select>
</div>
<!--多選選擇框,綁定到數(shù)組 data: {selected: []}-->
<div id="example-6">
<select v-model="selected" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
</select>
</div>
<!--v-model指令后份帐,可添加多個參數(shù)(number废境、lazy噩凹、trim)-->
<input v-model.number="age" type="number">
<input v-model.lazy="msg" >
<input v-model.trim="msg">
v-slot
: 插槽驮宴,主要用于內(nèi)容分發(fā)修己,插槽內(nèi)可以包含任何模板代碼睬愤,包括 HTML尤辱、其它組件等
<navigation-link url="/profile">
Your Profile
</navigation-link>
<!--然后你在 `<navigation-link>` 的模板中可能會寫為-->
<a v-bind:href="url" class="nav-link">
<!--當(dāng)組件渲染的時候啥刻,<slot></slot> 將會被替換為“Your Profile”娄涩。-->
<slot></slot>
</a>
<!--插槽內(nèi)可以包含任何模板代碼蓄拣,包括 HTML球恤、其它組件-->
<navigation-link url="/profile">
<!-- 添加一個 Font Awesome 圖標(biāo) (模板代碼)-->
<span class="fa fa-user"></span>
<!-- 添加一個圖標(biāo)的組件 -->
<font-awesome-icon name="user"></font-awesome-icon>
Your Profile
</navigation-link>
v-text
: 用于更新元素的 textContent
<span v-text="msg"></span>
<!--等價 -->
<span>{{msg}}</span>
v-html
: 用于更新元素的 innerHTML
<!--更新元素的 innerHTML,在網(wǎng)站上動態(tài)渲染任意 HTML 是非常危險的堪置,容易導(dǎo)致XSS攻擊。只在可信內(nèi)容上使用 `v-html`张惹,永不用在用戶提交的內(nèi)容上舀锨。-->
<div v-html="html"></div>
v-pre
: 用于跳過這個元素和它的子元素的編譯過程⊥鸲海可以用來顯示原始 Mustache 標(biāo)簽
<!--跳過這個元素和它的子元素的編譯過程坎匿。可以用來顯示原始 Mustache 標(biāo)簽。-->
<span v-pre>{{ this will not be compiled }}</span>
v-once
: 只渲染元素和組件一次告私。
<span v-once>這個將不會改變: {{ msg }}</span>
指令會在寫HTML時大量應(yīng)用到,特別是表單處理等承桥,建議多加練習(xí)驻粟。
組件
組件化的目的是擴(kuò)展HTML元素,封裝可重用代碼快毛;組件其實是可復(fù)用的 Vue 實例
基礎(chǔ)用法 格嗅,組件注冊 - 全局注冊:
// 定義名為 todo-item 的新組件
Vue.component('todo-item', {
template: '<li>這是組件內(nèi)容</li>',
})
var app = new Vue(...)
<ol>
<!-- 創(chuàng)建一個 todo-item 組件的實例 -->
<todo-item></todo-item>
</ol>
組件注冊 - 局部注冊:
var ComponentA = {
template:'<div>局部注冊組件的內(nèi)容</div>'
}
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
}
})
#局部注冊的組件在其子組件中不可用。例如唠帝,如果你希望 ComponentA 在 ComponentB 中可用屯掖,則你需要這樣寫:
var ComponentA = { /* ... */ }
var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
}
在模塊系統(tǒng)中局部注冊
#這樣 ComponentA 和 ComponentC 都可以在 ComponentB 的模板中使用了
import ComponentA from './ComponentA'
import ComponentC from './ComponentC'
export default {
components: {
ComponentA,
ComponentC
},
// ...
}
組件-數(shù)據(jù)傳遞:
props
:props 可以是數(shù)組或?qū)ο螅糜诮邮諄碜愿附M件的數(shù)據(jù)襟衰。
- 數(shù)組模式
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
- 對象模式
//若想每個prop 都指定的值類型贴铜。可以用對象形式列出prop瀑晒,屬性的名稱和值分別是prop 各自的名稱和類型
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
- Prop 驗證 绍坝,我們可為組件的 prop 指定驗證要求,例如你知道的這些類型苔悦。如果有一個需求沒有被滿足轩褐,則 Vue 會在瀏覽器控制臺中警告你。
Vue.component('my-component', {
props: {
// 基礎(chǔ)的類型檢查 (`null` 和 `undefined` 會通過任何類型驗證)
propA: Number,
// 多個可能的類型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 帶有默認(rèn)值的數(shù)字
propD: {
type: Number,
default: 100
},
// 帶有默認(rèn)值的對象
propE: {
type: Object,
// 對象或數(shù)組默認(rèn)值必須從一個工廠函數(shù)獲取
default: function () {
return { message: 'hello' }
}
},
// 自定義驗證函數(shù)
propF: {
validator: function (value) {
// 這個值必須匹配下列字符串中的一個
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
類型檢查 :
type
可以是下列原生構(gòu)造函數(shù)中的一個:
String
Number
Boolean
Array
Object
Date
Function
Symbol
給 prop 傳入數(shù)據(jù) - 示例:
<!--傳入一個靜態(tài)的值-->
<blog-post title="My journey with Vue"></blog-post>
<!--通過 v-bind 動態(tài)賦值-->
<blog-post v-bind:title="post.title"></blog-post>
<!-- 傳入數(shù)字玖详,這是一個 JavaScript 表達(dá)式而不是一個字符串-->
<blog-post v-bind:likes="42"></blog-post>
<!-- 傳入布爾值把介,包含該 prop 沒有值的情況在內(nèi),都意味著 `true`蟋座。-->
<blog-post is-published></blog-post>
<!--即便 `false` 是靜態(tài)的拗踢,我們?nèi)匀恍枰?`v-bind` 來告訴 Vue-->
<blog-post v-bind:is-published="false"></blog-post>
<!-- 用一個變量進(jìn)行動態(tài)賦值。-->
<blog-post v-bind:is-published="post.isPublished"></blog-post>
<!-- 傳入數(shù)組向臀,即便數(shù)組是靜態(tài)的巢墅,我們?nèi)匀恍枰?`v-bind` 來告訴 Vue-->
<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>
<!-- 傳入對象,即便對象是靜態(tài)的券膀,我們?nèi)匀恍枰?`v-bind` 來告訴 Vue -->
<blog-post
v-bind:author="{
name: 'Veronica',
company: 'Veridian Dynamics'
}"
></blog-post>
<!--傳入對象所有屬性 post: {id: 1,title: 'kevin'}-->
<blog-post v-bind="post"></blog-post>
<!--等價于-->
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
組件中君纫,data必需是函數(shù),因為它是引用類型芹彬,如果繼續(xù)使用對象庵芭,則會在組件復(fù)用時相互影響:
# 一個組件的 data 選項必須是一個函數(shù),因此每個實例可以維護(hù)一份被返回對象的獨立的拷貝
data: function () {
return {
count: 0
}
}
組件通信
- 父傳子props
所有的 prop 都使得其父子 prop 之間形成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中雀监,但是反過來則不行双吆。這樣會防止從子組件意外改變父級組件的狀態(tài)眨唬,從而導(dǎo)致你的應(yīng)用的數(shù)據(jù)流向難以理解。
- 子傳父
$emit
好乐,可以使用$emit
觸發(fā)父組件的自定義事件
// 父組件
Vue.component('parent', {
template:`
<div>
<child :message="message" v-on:getChildData="getChildData"></child>
</div>
`,
data() {
return {
message: 'hello'
}
},
methods:{
// 執(zhí)行子組件觸發(fā)的事件
getChildData(val) {
console.log(val);
}
}
});
// 子組件
Vue.component('child', {
template:`
<div>
<input type="text" v-model="myMessage" @input="passData(myMessage)">
</div>
`,
props:['message'],
data() {
return {
// 這里是必要的匾竿,因為你不能直接修改 props 的值
myMessage: this.message
}
},
methods:{
passData(val) {
// 數(shù)據(jù)狀態(tài)變化時觸發(fā)父組件中的事件
this.$emit('getChildData', val);
}
}
});
var app=new Vue({
el: '#app',
template: `
<div>
<parent />
</div>
`
});
- 非父子組件 : vuex,這部分暫時還沒深入學(xué)習(xí)蔚万,以后再展開詳解岭妖。
單文件組成
使用
Vue.componen
來定義全局組件,然后用new Vue({ el: '#container '})
在每個頁面內(nèi)指定一個容器元素反璃,在復(fù)雜的項目中會以下明顯缺點:
- 全局定義 (Global definitions) : 強(qiáng)制要求每個 component 中的命名不得重復(fù)
- 字符串模板 (String templates) : 缺乏語法高亮昵慌,在 HTML 有多行的時候,需要用到丑陋的 \
- 不支持 CSS (No CSS support) : 當(dāng) HTML 和 JavaScript 組件化時淮蜈,CSS 明顯被遺漏
- 沒有構(gòu)建步驟 (No build step) : 只能用 HTML 和 ES5 JavaScript斋攀,而不能使用預(yù)處理器,如Babel
針對以上缺點梧田,vue提供了文件擴(kuò)展名為 .vue 的 single-file components(單文件組件) 為以上所有問題提供了解決方法淳蔼,并且可以用 webpack 等構(gòu)建工具,好在vue提供了腳手架工具Vue CLI 官方地址
安裝Vue CLI
npm install -g @vue/cli
# OR
yarn global add @vue/cli
# 檢查其版本是否正確
vue --version
現(xiàn)在就可以通過Vue CLI創(chuàng)建工程裁眯,然后根據(jù)我們的需求配置并生成項目
vue create demo
# vue create 命令有一些可選項鹉梨,具體可查看
vue create --help
# 也能通過 vue ui 命令以圖形化界面創(chuàng)建和管理項目
vue ui
.vue文件結(jié)構(gòu)如下:
<template>...</template>
<script>...</script>
<style>...</style>
現(xiàn)在我們獲得:
- 完整語法高亮
- CommonJS 模塊
- 組件作用域的 CSS
至此,VUE的一些基本用法都已經(jīng)有大概的了解穿稳,后面還有更多知識要學(xué)習(xí)存皂,比如前面工程化
、vue第三方庫
等等逢艘。
vue生態(tài)之vue-router
Vue.js路由艰垂,允許我們通過不同的 URL 訪問不同的內(nèi)容,從而實現(xiàn)多視圖的單頁Web應(yīng)用
CDN方式
https://unpkg.com/vue-router/dist/vue-router.js
NPM方式安裝
cnpm install vue-router
vue-router應(yīng)用示例:<router-link> 是一個組件埋虹,該組件用于設(shè)置一個導(dǎo)航鏈接,切換不同 HTML 內(nèi)容娩怎。
to 屬性為目標(biāo)地址搔课, 即要顯示的內(nèi)容。
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<p>
<!-- <router-link> 默認(rèn)會被渲染成一個 `<a>` 標(biāo)簽 -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的組件將渲染在這里 -->
<router-view></router-view>
</div>
JS部分
// 0. 如果使用模塊化機(jī)制編程截亦,導(dǎo)入 Vue 和 VueRouter爬泥,要調(diào)用 Vue.use(VueRouter)
// 1. 定義(路由)組件。
// 可以從其他文件 import 進(jìn)來
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. 定義路由
// 每個路由應(yīng)該映射一個組件崩瓤。 其中"component" 可以是通過 Vue.extend() 創(chuàng)建的組件構(gòu)造器袍啡,或者,只是一個組件配置對象却桶。
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
// 3. 創(chuàng)建 router 實例境输,然后傳 `routes` 配置
const router = new VueRouter({
routes // (縮寫)相當(dāng)于 routes: routes
})
// 4. 創(chuàng)建和掛載根實例蔗牡。記得要通過 router 配置參數(shù)注入路由,從而讓整個應(yīng)用都有路由功能
const app = new Vue({
router
}).$mount('#app')
<router-link> 相關(guān)屬性
to
: 目標(biāo)路由的鏈接嗅剖。 當(dāng)被點擊后辩越,內(nèi)部會立刻把 to 的值傳到 router.push(),所以這個值可以是一個字符串或者是描述目標(biāo)位置的對象信粮。
<!-- 字符串 -->
<router-link to="home">Home</router-link>
<!-- 渲染結(jié)果 -->
<a href="home">Home</a>
<!-- 使用 v-bind 的 JS 表達(dá)式 黔攒; 不寫 v-bind 也可以,就像綁定別的屬性一樣-->
<router-link v-bind:to="'home'">Home</router-link>
<router-link :to="'home'">Home</router-link>
<router-link :to="{ path: 'home' }">Home</router-link>
<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
<!-- 帶查詢參數(shù)强缘,下面的結(jié)果為 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
replace
:設(shè)置 replace 屬性后督惰,點擊時會調(diào)用 router.replace() 而不是 router.push(),導(dǎo)航后不會留下 history 記錄旅掂。
<router-link :to="{ path: '/abc'}" replace></router-link>
append
:設(shè)置 append 屬性后赏胚,則在當(dāng)前 (相對) 路徑前添加基路徑。例如辞友,我們從 /a 導(dǎo)航到一個相對路徑 b栅哀,如果沒有配置 append,則路徑為 /b称龙,如果配了留拾,則為 /a/b
<router-link :to="{ path: 'relative/path'}" append></router-link>
tag
: 有時候想要 <router-link> 渲染成某種標(biāo)簽,例如 <li>鲫尊。 于是我們使用 tag prop 類指定何種標(biāo)簽痴柔,同樣它還是會監(jiān)聽點擊,觸發(fā)導(dǎo)航
<router-link to="/foo" tag="li">foo</router-link>
<!-- 渲染結(jié)果 -->
<li>foo</li>
active-class
:鏈接激活時使用的 CSS 類名疫向】任担可以通過以下代碼來替代。
exact-active-class
: 鏈接被精確匹配的時候應(yīng)該激活的 class
<router-link v-bind:to = "{ path: '/route1'}" active-class = "_active">Router Link 1</router-link>
<router-link v-bind:to = "{ path: '/route1'}" exact-active-class = "_active">Router Link 1</router-link>
event
: 聲明可以用來觸發(fā)導(dǎo)航的事件
<router-link v-bind:to = "{ path: '/route1'}" event = "mouseover">Router Link 1</router-link>