好傢伙,
1.使用場景
現在來,來想一下,作為一個使用Vue的開發者,假設現在我們要使用created(),我們會如何使用
1.1. .vue檔案中使用
<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>
<script>
export default {
created() {
this.message = 'Hello, created() in single file component!';
},
data() {
return {
message: ''
};
}
};
</script>
1.2. Vue例項中使用
<!DOCTYPE html>
<html>
<head>
<title>Vue created() example</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
<script>
new Vue({
el: '#app',
data: {
message: ''
},
created() {
this.message = 'Hello, created() in Vue instance!';
}
});
</script>
</body>
</html>
1.3. 混入
Vue.Mixin({ //全域性
created:function a(){
console.log('a----1')
}
})
那麼如果我這樣去定義
<script>
Vue.Mixin({ //全域性
created:function a(){
console.log('a----1')
}
})
Vue.Mixin({ //全域性
created:function b(){
console.log('b----2')
}
})
let vm = new Vue({
el: '#app', //編譯模板
// data: {
// },
data() {
// console.log(this)
return {
msg: 'hello',
a: {
b: 99
},
list: [1, 2, 3],
arr: [{
a: 1
}]
}
},
created(){
console.log(555)
}
})
</script>
是否會報錯呢?
答案是不會
對於created()
鉤子函式,在每個Vue例項建立時,會依次執行全域性混入函式中定義的created()
方法和例項本身定義的created()
方法。
當Vue例項被建立時,它會先執行全域性混入函式的對應生命週期鉤子函式,然後再執行例項本身的生命週期鉤子函式。
因此,在你的程式碼中,全域性混入函式中的created()
會在例項的created()
之前執行,且會按照它們在全域性混入函式中的定義順序執行。
這樣的設計允許開發者在多個地方定義相同的生命週期鉤子函式,以實現不同的功能擴充套件和邏輯處理。
同時,由於生命週期鉤子函式的執行順序已經確定,開發者可以根據需要合理安排程式碼邏輯
最後,也說明,created()定義的方法被合併處理了,所以我們要把這個"合併"實現
2.專案上下文
老樣子,先看看專案更新了哪些東西
程式碼已開源https://github.com/Fattiger4399/analytic-vue.git
2.1.Vue入口檔案index.js中
新增全域性方法
2.2. global-api/index.js
import { mergeOptions } from "../utils/index"
export function initGlobApi(Vue) {
//原始碼
//Vue.options ={created:[a,b,c],watch:{a,b}}
Vue.options ={}
Vue.Mixin = function (mixin) { // {}
//原始碼
//{created:[a,b,c],watch:[a,b]}
//物件的合併
console.log(999)
this.options = mergeOptions(this.options,mixin)
console.log(Vue.options,"||this is vue.options")
}
}
此處涉及我們的核心方法mergeOptions
這方法要實現一個怎麼樣的效果?
Vue.Mixin({ //全域性
created: function a() {
console.log('a----1')
}
})
Vue.Mixin({ //全域性
created: function b() {
console.log('b----2')
}
})
let vm = new Vue({
el: '#app', //編譯模板
// data: {
// },
data() {
// console.log(this)
return {
msg: 'hello',
a: {
b: 99
},
list: [1, 2, 3],
arr: [{
a: 1
}]
}
},
created() {
console.log(555)
}
})
將上述所有與created()有關的方法
最後合併到一個物件當中去
3.核心方法
3.1.utils/index.js
來到我們全篇最核心也是最難的部分
//物件合併 {created:[]}
export const HOOKS =[
"beforeCreated",
"created",
"beforeMount",
"mounted",
"beforeUpdate",
"updated",
"beforeDestory",
"destroyed",
]
// 策略模式
let starts ={}
starts.data =function(parentVal,childVal){
return childVal
} //合併data
starts.computed =function(){} //合併computed
starts.watch =function(){} //合併watch
starts.methods =function(){} //合併methods
//遍歷生命週期
HOOKS.forEach(hooks=>{
starts[hooks] = mergeHook
})
function mergeHook(parentVal,childVal){
if(childVal){
if(parentVal){
//把子元素合併進去
return parentVal.concat(childVal)
}else{
return [childVal] //[a]
}
}else{
return parentVal
}
}
export function mergeOptions(parent, child) {
console.log(parent,child,'||this is parent and child in mergeOptions()')
const options ={}
//判斷父親
for(let key in parent){
console.log(key,'||this is key')
mergeField(key)
}
//判斷兒子
for(let key in child){
console.log(key,'||this is key')
mergeField(key)
}
function mergeField(key){
//根據key 策略模式
if(starts[key]){ //created {created:[a]}
options[key] =starts[key](parent[key],child[key])
}else{
options[key] = child[key]
}
}
return options
}
這玩意要看懂,必須先把這玩意學了,策略模式
一句話概括策略模式是一種行為型設計模式,它允許在執行時根據不同的情境選擇並應用不同的演算法或行為(不是條件判斷)
挖個坑,後面會補一章策略模式
//物件合併 {created:[]}
export const HOOKS =[
"beforeCreated",
"created",
"beforeMount",
"mounted",
"beforeUpdate",
"updated",
"beforeDestory",
"destroyed",
]
// 策略模式
let starts ={}
starts.data =function(parentVal,childVal){
return childVal
} //合併data
starts.computed =function(){} //合併computed
starts.watch =function(){} //合併watch
starts.methods =function(){} //合併methods
//遍歷生命週期
HOOKS.forEach(hooks=>{
starts[hooks] = mergeHook
})
function mergeHook(parentVal,childVal){
if(childVal){
if(parentVal){
//把子元素合併進去
return parentVal.concat(childVal)
}else{
return [childVal] //[a]
}
}else{
return parentVal
}
}
這裡定義常量HOOKS包含了一組生命週期鉤子的名字
隨後建立starts物件,用於儲存各個不同屬性的不同合併策略
至於mergeHook,這就是個簡單的合併方法,不用多解釋了
再來看下半部分
export function mergeOptions(parent, child) {
console.log(parent,child,'||this is parent and child in mergeOptions()')
const options ={}
//判斷父親
for(let key in parent){
console.log(key,'||this is key')
mergeField(key)
}
//判斷兒子
for(let key in child){
console.log(key,'||this is key')
mergeField(key)
}
function mergeField(key){
//根據key 選擇不同策略區處理
if(starts[key]){ //created {created:[a]}
options[key] =starts[key](parent[key],child[key])
}else{
options[key] = child[key]
}
}
return options
}
mergeOptions將父項和子項合併成一個新的物件
這個你真的得親自上手除錯一下
3.2.init.js
這句就是將在option合併Vue.option中並返回給vm.$options
(option為new Vue時帶的引數)
最後,看看效果
將方法都合併到了created中