文章將講述指令、混入、高階組件、函數式組件、@hook、異步組件等內容。若是文中有不當的地方歡迎指正哦!html
除了核心功能默認內置的指令 (v-model 和 v-show),Vue 也容許註冊自定義指令。有時候咱們想對dom進行操做的時候,就可使用自定義指令,好比設置標題樣式而且讓標題一直固定在頁面上方,可使用全局註冊或者局部註冊。而後你能夠在模板中任何元素上使用新的 v-title property。vue
//全局註冊
<div id="app">
<div v-title>hello world</div>
</div>
<script>
Vue.directive('title', {
inserted: function (el) {
console.log(el)
el.style.position = 'fixed'
el.style.top = '50px'
el.style.left = '48%'
el.style.color = '#409EFF'
}
})
new Vue({
el: '#app',
data: {
message: 'hello!'
}
})
</script>
<style>
#app{
height: 1000px
}
</style>
//局部註冊
new Vue({
el: '#app',
directives: {
title: {
inserted: function (el) {
console.log(el)
el.style.position = 'fixed'
el.style.top = '50px'
el.style.left = '48%'
el.style.color = '#409EFF'
}
}
}
})
複製代碼
指令鉤子函數會被傳入如下參數:node
咱們打印下函數傳入的參數,其實簡單來講就是el就是綁定dom元素,binging指令:後所攜帶的具體內容,VNode就當還未生成的節點好了。webpack
<div v-title:arr="message">hello world</div>
Vue.directive('title', {
inserted: function (el, binding, vnode) {
console.log(el, binding, vnode)
el.style.position = 'fixed'
el.style.top = '50px'
el.style.left = '48%'
el.style.color = '#409EFF'
}
})
複製代碼
一個指令定義對象能夠提供以下幾個鉤子函數 (均爲可選):es6
咱們能夠測試下鉤子函數的調用時機:web
<div id="app">
<div id="txt" v-title:data="sum">value: {{sum}}</div>
</div>
<script>
new Vue({
el: '#app',
data: {
sum: 0
},
directives: {
title: {
bind: (el, bind) => { console.log(bind.value, 'a') },// 第一次綁定元素時調用
inserted: (el, bind) => { console.log(bind.value, 'b') },// 當被綁定的元素插入到 DOM 中時……
update: (el, bind) => { console.log(bind.value, 'c') },// 所在組件VNode發生更新時調用
componentUpdated: (el, bind) => { console.log(bind.value, 'd') }, // 指令所在組件的 VNode 及其子 VNode 所有更新後調用
unbind: (el, bind) => { console.log(bind.value, 'e') } // 只調用一次,指令與元素解綁時調用
}
},
mounted() {
console.log(this.sum, '???')
let timer = setInterval(() => {
this.sum++
}, 200)
setTimeout(() => {
clearInterval(timer)
}, 3000)
}
})
</script>
複製代碼
在頁面渲染的過程當中,分別有建立(create)、激活(avtivate)、更新(update)、移除(remove)、銷燬(destroy),在這些過程當中,框架在每一個時段都會調用相應的鉤子函數,這些hooks中一部分的函數就包含了咱們的指令。源碼部分我瞭解的很少,給你們推薦一篇vue指令原理相關博文www.cnblogs.com/gerry2019/p…vue-router
官方是這樣定義的:混入 (mixin) 提供了一種很是靈活的方式,來分發 Vue 組件中的可複用功能。一個混入對象能夠包含任意組件選項。當組件使用混入對象時,全部混入對象的選項將被「混合」進入該組件自己的選項。其實就是vue實例的一個複用。實用場景:公共組件或者功能,例如獲取用戶白名單、菜單返回、公共基礎table。 值得注意的點:vue-cli
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// => { message: "goodbye", foo: "abc", bar: "def" }
}
})
複製代碼
一個函數接受一個組件爲參數,返回一個包裝後的組件。其實在vue中,組件能夠當作一個函數,那從本質上來講,高階組件就是高階函數(JavaScript的函數其實都指向某個變量。既然變量能夠指向函數,函數的參數能接收變量,那麼一個函數就能夠接收另外一個函數做爲參數,這種函數就稱之爲高階函數)express
舉例一個最簡單的高階函數計算次方api
function pow(x, y, f){
return f(x, y);
}
pow(3, 3, Math.pow)
複製代碼
在es6中也有不少高階函數,如map、reduce、filter。
<div id="app">
<hoc></hoc>
</div>
<script>
const view = {
template: `<span>
<span>test hoc ...</span>
</span>`,
props: ["result", "loading"],
};
const test = (wrapped, txt = 'hello') => {
return {
render(h) {
const args = {
props: {
result: this.result,
loading: this.loading,
},
};
const wrapper = h("div", [
h(wrapped, args),
'loading'
]);
return wrapper
}
}
}
const hoc = test(view, 'hui')
console.log(hoc);
new Vue({
el: '#app',
components: {
hoc
},
data: {
sum: 0
}
})
</script>
複製代碼
能夠在同組件之間進行動態切換, 動態切換能夠經過 Vue 的 元素加一個特殊的 is attribute 來實現:
<!-- 組件會在 `currentTabComponent` 改變時改變 -->
<!DOCTYPE html>
<html>
<head>
<title>Dynamic Components Example</title>
<script src="https://unpkg.com/vue"></script>
<style>
.tab-button {
padding: 6px 10px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border: 1px solid #ccc;
cursor: pointer;
background: #f0f0f0;
margin-bottom: -1px;
margin-right: -1px;
}
.tab-button:hover {
background: #e0e0e0;
}
.tab-button.active {
background: #e0e0e0;
}
.tab {
border: 1px solid #ccc;
padding: 10px;
}
</style>
</head>
<body>
<div id="dynamic-component-demo" class="demo">
<button
v-for="tab in tabs"
v-bind:key="tab"
v-bind:class="['tab-button', { active: currentTab === tab }]"
v-on:click="currentTab = tab"
>
{{ tab }}
</button>
<component v-bind:is="currentTabComponent" class="tab"></component>
</div>
<script>
Vue.component("tab-home", {
template: "<div>Home component</div>"
});
Vue.component("tab-posts", {
template: "<div>Posts component</div>"
});
Vue.component("tab-archive", {
template: "<div>Archive component</div>"
});
new Vue({
el: "#dynamic-component-demo",
data: {
currentTab: "Home",
tabs: ["Home", "Posts", "Archive"]
},
computed: {
currentTabComponent: function() {
return "tab-" + this.currentTab.toLowerCase();
}
}
});
</script>
</body>
</html>
複製代碼
在大型應用中,咱們可能須要將應用分割成小一些的代碼塊,而且只在須要的時候才從服務器加載一個模塊。爲了簡化,Vue 容許你以一個工廠函數的方式定義你的組件,這個工廠函數會異步解析你的組件定義。Vue 只有在這個組件須要被渲染的時候纔會觸發該工廠函數,且會把結果緩存起來供將來重渲染。
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// 向 `resolve` 回調傳遞組件定義
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
複製代碼
在vue-cli中在使用異步組件
const first =()=>import(/* webpackChunkName: "group-foo" */ "../components/first.vue");
複製代碼
Vue 實例同時在其事件接口中提供了其它的方法。咱們能夠:
經過 $on(eventName, eventHandler) 偵聽一個事件
經過 $once(eventName, eventHandler) 一次性偵聽一個事件
經過 $off(eventName, eventHandler) 中止偵聽一個事件
你一般不會用到這些,可是當你須要在一個組件實例上手動偵聽事件時,它們是派得上用場的。它們也能夠用於代碼組織工具。例如,你可能常常看到這種集成一個第三方庫的模式。官網提供一個案例:在不使用beforeDestroy鉤子清picker
//案例一
mounted: function () {
var picker = new Pikaday({
field: this.$refs.input,
format: 'YYYY-MM-DD'
})
this.$once('hook:beforeDestroy', function () {
picker.destroy()
})
}
//案例二
//在父組件在子組件渲染階段作一些操做
<child
@hook:mounted="handle"
@hook:beforeUpdated="xxx"
@hook:updated="xxx"
/>
method () {
handle() {
// do something...
}
},
複製代碼
在vue生命週期中週期都有對應的鉤子函數
插件一般用來爲 Vue 添加全局功能。插件的功能範圍沒有嚴格的限制——通常有下面幾種:
添加全局方法或者 property。如:vue-custom-element
添加全局資源:指令/過濾器/過渡等。如 vue-touch
經過全局混入來添加一些組件選項。如 vue-router
添加 Vue 實例方法,經過把它們添加到 Vue.prototype 上實現。
一個庫,提供本身的 API,同時提供上面提到的一個或多個功能。如 vue-router
自定義插件
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或 property
Vue.myGlobalMethod = function () {
// 邏輯...
}
// 2. 添加全局資源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 邏輯...
}
...
})
// 3. 注入組件選項
Vue.mixin({
created: function () {
// 邏輯...
}
...
})
// 4. 添加實例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 邏輯...
}
}
複製代碼
文章都在在官網文檔上的整理和概括,只是停留在表層,歡迎你們指正。定下 下一個目標:寫一個小型vue-router。
vue官網 cn.vuejs.org/v2/api
探索Vue高階組件 www.jianshu.com/p/6b149189e…
Vue 進階必學之高階組件 HOC zhuanlan.zhihu.com/p/126552443
Vue指令實現原理 www.cnblogs.com/gerry2019/p…