Vue.js 組件
組件(Component)是 Vue.js 最強大的功能之一,
組件可以擴展 HTML 元素,封裝可重用的代碼,
<template> <div id="app"> <!-- 使用自定義組件 --> <runoob></runoob> </div> </template> <script> import Vue from 'vue' // 注冊組件 Vue.component('runoob', { template: '<h1>自定義組件!</h1>' }) var count=1; export default { name: 'App', data(){ return{ } }, methods:{ }, } </script> <style scoped> </style>
也可以在實體選項中注冊區域組件,這樣組件只能在這個實體中使用:
<template> <div id="app"> <!-- 使用自定義組件 --> <runoob></runoob> </div> </template> <script> import Vue from 'vue' var Child = { template: '<h1>自定義組件!</h1>' } var count=1; export default { name: 'App', data(){ return{ } }, components:{ 'runoob':Child }, methods:{ }, } </script> <style scoped> </style>
prop 是子組件用來接受父組件傳遞過來的資料的一個自定義屬性,
父組件的資料需要通過 props 把資料傳給子組件,子組件需要顯式地用 props 選項宣告 "prop":
<template> <div id="app"> <!-- 使用自定義組件 --> <child msg="hello,cyy"></child> </div> </template> <script> import Vue from 'vue' Vue.component('child',{ props:['msg'], template:'<span>{{msg}}</span>' }) var count=1; export default { name: 'App', data(){ return{ } }, methods:{ }, } </script> <style scoped> </style>

類似于用 v-bind 系結 HTML 特性到一個運算式,也可以用 v-bind 動態系結 props 的值到父組件的資料中,每當父組件的資料變化時,該變化也會傳導給子組件:
<template> <div id="app"> <input type="text" v-model="info"> <!-- 使用自定義組件 --> <child v-bind:msg="info"></child> </div> </template> <script> import Vue from 'vue' Vue.component('child',{ props:['msg'], template:'<span>template content: {{msg}}</span>' }) var count=1; export default { name: 'App', data(){ return{ info:'' } }, methods:{ }, } </script> <style scoped> </style>

以下實體中使用 v-bind 指令將 item傳到每一個重復的組件中:
<template> <div id="app"> <!-- 使用自定義組件 --> <child v-for="(item,index) in list" :key="index" v-bind:msg="item.name"></child> </div> </template> <script> import Vue from 'vue' Vue.component('child',{ props:['msg'], template:'<span>{{msg}}<br></span>' }) var count=1; export default { name: 'App', data(){ return{ list:[ { name:'cyy1' }, { name:'cyy2' }, { name:'cyy3' } ] } }, methods:{ }, } </script> <style scoped> </style>

注意: prop 是單向系結的:當父組件的屬性變化時,將傳導給子組件,但是不會反過來,
組件可以為 props 指定驗證要求,
為了定制 prop 的驗證方式,你可以為 props 中的值提供一個帶有驗證需求的物件,而不是一個字串陣列,例如:
Vue.component('my-component', {
props: {
// 基礎的型別檢查 (`null` 和 `undefined` 會通過任何型別驗證)
propA: Number,
// 多個可能的型別
propB: [String, Number],
// 必填的字串
propC: {
type: String,
required: true
},
// 帶有默認值的數字
propD: {
type: Number,
default: 100
},
// 帶有默認值的物件
propE: {
type: Object,
// 物件或陣列默認值必須從一個工廠函式獲取
default: function () {
return { message: 'hello' }
}
},
// 自定義驗證函式
propF: {
validator: function (value) {
// 這個值必須匹配下列字串中的一個
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
當 prop 驗證失敗的時候,(開發環境構建版本的) Vue 將會產生一個控制臺的警告,
type 可以是下面原生構造器:
StringNumberBooleanArrayObjectDateFunctionSymbol
type 也可以是一個自定義構造器,使用 instanceof 檢測,
父組件是使用 props 傳遞資料給子組件,但如果子組件要把資料傳遞回去,就需要使用自定義事件!
我們可以使用 v-on 系結自定義事件, 每個 Vue 實體都實作了事件介面(Events interface),即:
- 使用
$on(eventName)監聽事件 - 使用
$emit(eventName)觸發事件
另外,父組件可以在使用子組件的地方直接用 v-on 來監聽子組件觸發的事件,
以下實體中子組件已經和它外部完全解耦了,它所做的只是觸發一個父組件關心的內部事件,
<template> <div id="app"> <!-- 使用自定義組件 --> <child @add-count="addCount"></child> <child @add-count="addCount"></child> <p>{{total}}</p> </div> </template> <script> import Vue from 'vue' Vue.component('child',{ template:'<button @click="addNum">click me</button>', data(){ return{ num:0 } }, methods:{ addNum(){ this.num+=1; this.$emit('add-count'); } } }) var count=1; export default { name: 'App', data(){ return{ total:0 } }, methods:{ addCount(){ this.total+=1; } }, } </script> <style scoped> </style>
如果你想在某個組件的根元素上監聽一個原生事件,可以使用 .native 修飾 v-on ,例如:
<my-component v-on:click.native="doTheThing"></my-component>
子組件通過 $emit 觸發父組件的方法時,如果需要傳遞引數,可在方法名后面加可選引數,引數以逗號隔開,
比如 $emit("FunctionName") 當要傳遞引數時 :$emit("FunctionName",[arg1,arg2...]),
Vue.js 自定義指令
除了默認設定的核心指令( v-model 和 v-show ), Vue 也允許注冊自定義指令,
下面我們注冊一個全域指令 v-focus, 該指令的功能是在頁面加載時,元素獲得焦點:
<template> <div id="app"> <input type="text" v-focus> </div> </template> <script> import Vue from 'vue' //注冊自定義指令v-focus Vue.directive('focus',{ inserted:function(el){ el.focus(); } }) var count=1; export default { name: 'App', data(){ return{ } }, methods:{ }, } </script>
也可以在實體使用 directives 選項來注冊區域指令,這樣指令只能在這個實體中使用:
<template> <div id="app"> <input type="text" v-focus> </div> </template> <script> import Vue from 'vue' var count=1; export default { name: 'App', data(){ return{ } }, directives:{//注冊自定義指令v-focus focus:{ inserted:function(el){ el.focus(); } } } } </script>
指令定義函式提供了幾個鉤子函式(可選):
-
bind: 只呼叫一次,指令第一次系結到元素時呼叫,用這個鉤子函式可以定義一個在系結時執行一次的初始化動作, -
inserted: 被系結元素插入父節點時呼叫(父節點存在即可呼叫,不必存在于 document 中), -
update: 被系結元素所在的模板更新時呼叫,而不論系結值是否變化,通過比較更新前后的系結值,可以忽略不必要的模板更新(詳細的鉤子函式引數見下), -
componentUpdated: 被系結元素所在模板完成一次更新周期時呼叫, -
unbind: 只呼叫一次, 指令與元素解綁時呼叫,
鉤子函式的引數有:
- el: 指令所系結的元素,可以用來直接操作 DOM ,
- binding: 一個物件,包含以下屬性:
- name: 指令名,不包括
v-前綴, - value: 指令的系結值, 例如:
v-my-directive="1 + 1", value 的值是2, - oldValue: 指令系結的前一個值,僅在
update和componentUpdated鉤子中可用,無論值是否改變都可用, - expression: 系結值的運算式或變數名, 例如
v-my-directive="1 + 1", expression 的值是"1 + 1", - arg: 傳給指令的引數,例如
v-my-directive:foo, arg 的值是"foo", - modifiers: 一個包含修飾符的物件, 例如:
v-my-directive.foo.bar, 修飾符物件 modifiers 的值是{ foo: true, bar: true },
- name: 指令名,不包括
- vnode: Vue 編譯生成的虛擬節點,
- oldVnode: 上一個虛擬節點,僅在
update和componentUpdated鉤子中可用,
<template> <div id="app"> <div v-cyy:hello.a.b="msg"></div> </div> </template> <script> import Vue from 'vue' //自定義指令cyy Vue.directive('cyy',{ bind:function(el,binding,vnode){ el.innerHTML=` 指令名:${JSON.stringify(binding.name)}<br/> 指令的系結值:${JSON.stringify(binding.value)}<br/> 指令系結的前一個值:${JSON.stringify(binding.oldValue)}<br/> 系結值的運算式或變數名:${JSON.stringify(binding.expression)}<br/> 傳給指令的引數:${JSON.stringify(binding.arg)}<br/> 一個包含修飾符的物件:${JSON.stringify(binding.modifiers)}<br/> 虛擬節點的鍵值:${Object.keys(vnode).join(', ')}<br/> `; } }) export default { name: 'App', data(){ return{ msg:'i am cyy' } }, } </script>

不需要其他鉤子函式時,可以簡寫函式,如下格式
<template> <div id="app"> <div v-cyy:backgroundColor="styleCls">this is a text</div> </div> </template> <script> import Vue from 'vue' //自定義指令cyy Vue.directive('cyy',{ bind:function(el,binding){ el.style.backgroundColor=binding.value.backgroundColor; } }) export default { name: 'App', data(){ return{ styleCls:{ backgroundColor:'pink' } } }, } </script>

指令函式可接受所有合法的 JavaScript 運算式,以下實體傳入了 JavaScript 物件:
<template> <div id="app"> <div v-cyy="{text:text,color:color}">this is a text</div> </div> </template> <script> import Vue from 'vue' //自定義指令cyy Vue.directive('cyy',{ bind:function(el,binding){ el.innerHTML=binding.value.text; el.style.color=binding.value.color; } }) export default { name: 'App', data(){ return{ text:'cyy', color:'orange' } }, } </script>

Vue.js 路由 推薦使用淘寶鏡像:
cnpm install vue-router

<router-link> 是一個組件,該組件用于設定一個導航鏈接,切換不同 HTML 內容, to 屬性為目標地址, 即要顯示的內容,
以下實體中我們將 vue-router 加進來,然后配置組件和路由映射,再告訴 vue-router 在哪里渲染它們,代碼如下所示:
使用模塊化機制編程,匯入 Vue 和 VueRouter,要呼叫 Vue.use(VueRouter)
App.vue
<template> <div id="app"> <p> <!-- 通過傳入 `to` 屬性指定鏈接. --> <!-- <router-link> 默認會被渲染成一個 `<a>` 標簽 --> <router-link to="/">home page</router-link> <router-link to="/next">next page</router-link> </p> <!-- 路由匹配到的組件將渲染在這里 --> <router-view></router-view> </div> </template> <script> import Vue from 'vue' export default { name: 'App', data(){ return{ } }, } </script>
router/index.js
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' //1. 定義(路由)組件,可以從其他檔案 import 進來 const Next = { template: '<div>next</div>' } const routes = [ { path: '/Next', component: Next }, { path: '/', component: HelloWorld }, ] Vue.use(Router) export default new Router({ routes })
效果圖


點擊過的導航鏈接都會加上樣式 class ="router-link-exact-active router-link-active",
to
表示目標路由的鏈接, 當被點擊后,內部會立刻把 to 的值傳到 router.push(),所以這個值可以是一個字串或者是描述目標位置的物件,
<!-- 字串 --> <router-link to="home">Home</router-link> <!-- 渲染結果 --> <a href="home">Home</a> <!-- 使用 v-bind 的 JS 運算式 --> <router-link v-bind:to="'home'">Home</router-link> <!-- 不寫 v-bind 也可以,就像系結別的屬性一樣 --> <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> <!-- 帶查詢引數,下面的結果為 /register?plan=private --> <router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
replace
設定 replace 屬性的話,當點擊時,會呼叫 router.replace() 而不是 router.push(),導航后不會留下 history 記錄,
<router-link :to="{ path: '/abc'}" replace></router-link>
append
設定 append 屬性后,則在當前 (相對) 路徑前添加基路徑,例如,我們從 /a 導航到一個相對路徑 b,如果沒有配置 append,則路徑為 /b,如果配了,則為 /a/b
<router-link :to="{ path: 'relative/path'}" append></router-link>
tag
有時候想要 <router-link> 渲染成某種標簽,例如 <li>, 于是我們使用 tag prop 類指定何種標簽,同樣它還是會監聽點擊,觸發導航,
<router-link to="/foo" tag="li">foo</router-link> <!-- 渲染結果 --> <li>foo</li>
active-class
設定 鏈接激活時使用的 CSS 類名,可以通過以下代碼來替代,
<style> ._active{ background-color : red; } </style> <p> <router-link v-bind:to = "{ path: '/route1'}" active-class = "_active">Router Link 1</router-link> <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link> </p>
注意這里 class 使用 active_,
exact-active-class
配置當鏈接被精確匹配的時候應該激活的 class,可以通過以下代碼來替代,
<p> <router-link v-bind:to = "{ path: '/route1'}" exact-active-class = "_active">Router Link 1</router-link> <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link> </p>
event
宣告可以用來觸發導航的事件,可以是一個字串或是一個包含字串的陣列,
<router-link v-bind:to = "{ path: '/route1'}" event = "mouseover">Router Link 1</router-link>
以上代碼設定了 event 為 mouseover ,及在滑鼠移動到 Router Link 1 上時導航的 HTML 內容會發生改變,
exact-active-class 和 active-class 的區別
router-link 默認情況下的路由是模糊匹配,例如當前路徑是 /article/1 那么也會激活 <router-link to="/article">,所以當設定 exact-active-class 以后,這個 router-link 只有在當前路由被全包含匹配時才會被激活 exact-active-class 中的 class,例如:
<router-link to="/article" active-class="router-active"></router-link>
當用戶訪問 /article/1 時會被激活為:
<a href="#/article" class="router-active" rel="nofollow"></a>
而當使用:
<router-link to="/article" exact-active-class="router-active"></router-link>
當用戶訪問 /article/1 時,不會激活這個 link 的 class:
<a href="#/article" rel="nofollow"></a>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/115156.html
標籤:JavaScript
