preface
This article is mainly written by vue2 0 source code Mixin mixing principle
In the last article, we mainly introduced Vue Asynchronous update principle The core is to use nextTick to realize asynchronous queue. This article mainly includes Mixin mixing, which is a very key api in Vue. It plays an important role in merging options during Vue initialization
Applicable crowd: students who don't have time to see the official source code or who are ignorant of the source code and don't want to see it
text
Vue.mixin({ created() { console.log("I'm a global Infiltrator"); }, }); // Vue instantiation let vm = new Vue({ el: "#app", data() { return { a: { a: { a: { b: 456 } } }, aa: 1, bb: 2, }; }, created() { console.log("I'm my own"); }, template: `<div id="a">hello I wrote it myself Vue{{name}} </div>`, }); Copy code
When we want to reuse a piece of business code logic in Vue, we often use the method of mixing, but do you know the principle of mixing, the order of mixing and the merging strategy of different options? Let's write it together
1. Define global Mixin function
// src/global-api/mixin.js import {mergeOptions} from '../util/index' export default function initMixin(Vue){ Vue.mixin = function (mixin) { // Merge objects this.options=mergeOptions(this.options,mixin) }; } }; Copy code
Create a new global API folder and define mixin as the global method of Vue. The core method is to use mergeOptions to mix the incoming options into your own options
// src/index.js import { initMixin } from "./init.js"; // Vue is a constructor instantiated by the new keyword function Vue(options) { // Vue initialization starts here this._init(options); } // This practice is conducive to code segmentation initMixin(Vue); export default Vue; Copy code
Then, the initMixin method is introduced into the Vue entry file
2.mergeOptions method
// src/util/index.js // Define lifecycle export const LIFECYCLE_HOOKS = [ "beforeCreate", "created", "beforeMount", "mounted", "beforeUpdate", "updated", "beforeDestroy", "destroyed", ]; // Merge strategy const strats = {}; //Lifecycle consolidation strategy function mergeHook(parentVal, childVal) { // If you have a son if (childVal) { if (parentVal) { // Merge into an array return parentVal.concat(childVal); } else { // Wrap into an array return [childVal]; } } else { return parentVal; } } // Add merge policy for lifecycle LIFECYCLE_HOOKS.forEach((hook) => { strats[hook] = mergeHook; }); // mixin core method export function mergeOptions(parent, child) { const options = {}; // Traversal father for (let k in parent) { mergeFiled(k); } // A father has no son for (let k in child) { if (!parent.hasOwnProperty(k)) { mergeFiled(k); } } //Real merge field method function mergeFiled(k) { if (strats[k]) { options[k] = strats[k](parent[k], child[k]); } else { // Default policy options[k] = child[k] ? child[k] : parent[k]; } } return options; } Copy code
Let's first focus on the mergeOptions method, which is mainly used to traverse the attributes of father and son for merging. If the merged options have their own merging strategy, then the corresponding merging strategy is used
Let's take a look at the merge strategy of the life cycle here. mergeHook obviously mixes all the life cycles into an array and calls them in turn
3. Call of life cycle
// src/lifecycle.js export function callHook(vm, hook) { // Execute the methods corresponding to the life cycle in turn const handlers = vm.$options[hook]; if (handlers) { for (let i = 0; i < handlers.length; i++) { handlers[i].call(vm); //this in the life cycle points to the current instance } } } Copy code
Call by traversing the life cycle above $options in turn
// src/init.js Vue.prototype._init = function (options) { const vm = this; // this here represents the call_ Object of init method (instance object) // this.$options are the attributes and global Vue that are passed in when the user creates new Vue Options merged results vm.$options = mergeOptions(vm.constructor.options, options); callHook(vm, "beforeCreate"); //Before initializing data // Initialization status initState(vm); callHook(vm, "created"); //After initializing data // Template rendering if there is el attribute if (vm.$options.el) { vm.$mount(vm.$options.el); } }; Copy code
During init initialization, call mergeOptions to merge options, and then use callHook to execute the relevant methods passed in by the user where the life cycle needs to be called
// src/lifecycle.js export function mountComponent(vm, el) { vm.$el = el; // Introduce the concept of watcher. Here, register a render watcher to execute VM_ The update (VM. _render()) method renders the view callHook(vm, "beforeMount"); //Before initial rendering let updateComponent = () => { vm._update(vm._render()); }; new Watcher( vm, updateComponent, () => { callHook(vm, "beforeUpdate"); //Before update }, true ); callHook(vm, "mounted"); //After rendering } Copy code
Call the relevant lifecycle callHook in the mountComponent method
4. Mixed mind map
Summary
So far, Vue's hybrid prototype has been written. In fact, the core is the object merging and the merging strategy of different options. At present, it only demonstrates the merging strategy of the life cycle. Later, when it comes to the component, it will talk about the merging strategy related to the component. You can look at the mind map and write the core code yourself. In case of incomprehension or controversy, you are welcome to comment and leave a message
Finally, if you think this article is helpful, remember to praise Sanlian Oh, thank you very much!