People say that interview makes rocket, work screws, in fact, we can understand, if not so how can prove your ability to learn? And blind date is the same truth, the first blind date, you wear tattered clothes into, should also have no below? Ha ha

My biggest characteristic is lazy, always don’t like special long article, this 100 lines of code to achieve the VUE MVVM two-way binding principle, basically all points have notes, and basically all plain English, no bureaucratic and formulaic, learned JS you will be able to understand… Did not learn JS to learn JS first and then come over

This simplifies some unnecessary version of the code, such as many data agent and hijacked the separation, I directly, at the same time like to read novels, as long as you spend 10 minutes, you will be able to fully understand, would be better if I can write again, don’t think the code is long, less than 100 lines, actually,, don’t be afraid of, dare to gamble?

HTML looks like this… There’s nothing to tell

 <div id="app">
        <input type="text" v-model="text">
        {{ text }}
        <button @click="reset" >reset</button>
    </div>
    <script>
        var vm = new saoVm({
            el: 'app',
            data: {
                text: ' '
            },
            methods: {
                reset() {
                    this.text = ' '; ,}}});</script>
Copy the code

Here comes the big part. Hold your breath for 10 minutes… First glance over the shelf structure, then look at…

class saoVm {
    constructor(options) {
        const {
            el,
            data,
            methods
        } = options;
        this.methods = methods;
        this.target = null;
        // Publish initialization
        this.observe(this, data);
        // Subscription initialization
        this.compile(document.getElementById(el));
    }
    /* Why object.defineProperty? Isn't two-way binding where when you set a value, you change the view, the view changes, the value changes? So I have to know when he's setting the value, when he's changing the view? This is done using the API's get and set functions, which I won't go into detail on. */ is implemented by overriding data's set and get functions by looping through properties in data and defining each property in data via Object.defineProperty
    observe(root, data) {
        for (const key in data) {
            this.defineReactive(root, key, data[key]);
        }
    }

    defineReactive(root, key, value) {
        /* If data is data:{foo:{bar: GGG}} /* If data is data:{foo:{bar: GGG}} /* If data is data:{foo:{bar: GGG}} /* If data is data:{foo:{bar: GGG}} Here we use recursion to determine the value of value (i.e. Data.foo) and data hijacking */
        if (typeof value == 'object') {
            return this.observe(value, value);
        }
        const dep = new Dispatcher();
        /* The first parameter is this.data. XXX, which can then be accessed by this. XXX, but also overwrites get and set
        Object.defineProperty(root, key, {
            set(newValue) {
                // If the value is the same as before, no processing is done
                if (value == newValue) return;
                value = newValue;
                // Data change notification triggers view replacement, which is called publishing
                dep.notify(newValue);
            },
            get() {
                /* The add process is called a subscription. What is this.target here? In the compile phase you will get the answer, look down at */
                dep.add(this.target);
                returnvalue; }}); }// Compile the template - that is, replace {{MSG}} with the real value of MSG
    compile(dom) {
        // Get all the children of the dom node $el (note the difference between node and element nodes)
        const nodes = dom.childNodes;
        // Start traversing all nodes... (note: for... In gets the key,for... Of gets value)
        for (const node of nodes) {
            //nodeType is 1 for element node, 2 for attribute node, and 3 for text node.
            // There is no need to care about the attribute node,, and can be removed
            // Element node
            if (node.nodeType == 1) {
                // Get all the element attributes, such as V-model,style,@click, etc
                const attrs = node.attributes;
                for (const attr of attrs) {
                    // If the attribute name is V-model
                    if (attr.name == 'v-model') {
                        const name = attr.value;
                        // Bind the input event
                        node.addEventListener('input', e = >{
                        /* For example, v-model=" XXX "below the purpose of this. XXX = input value, change the data set value in the data will trigger the publication of the subscription, and then update the view */
                            this[name] = e.target.value;
                        });
                        /* Remember that hole? What is this.target? This is an instance of watcher. Each watcher has an update method that performs a view update. Target = this.target = this.target = this.target = this.target = this.target
                        this.target = new Watcher(node, 'input');
                        // This step is purely to trigger the property's GET method
                        // To subscribe to events, execute the addS method in GET
                        this[name];
                    }
                    // if it is @click, listen for events for this node
                    if (attr.name == '@click') {
                        const name = attr.value;
                        node.addEventListener('click'.this.methods[name].bind(this)); }}}// text node --
            if (node.nodeType == 3) {
                {{XXX}} - {{XXX}
                const reg = / \ {\ {(. *) \} \} /;
                // node.nodeValue is equivalent to innerText
                const match = node.nodeValue.match(reg);
                if (match) {
                    // match[1], match[1]
                    // match the contents of the parentheses and remove the Spaces
                    const name = match[1].trim();
                    // There is no need to explain. I explained it up here, but again, here
                    // The second argument is because input updates the view to change its value
                    // Other text nodes change their nodeValue,
                    // Therefore, when there is this input parameter to distinguish
                    this.target = new Watcher(node, 'text');
                    this[name];
                    // This step is to replace {{XXX}} with null
                    node.nodeValue = ' ';
                }
            }
        }
    }
}

class Dispatcher {
    constructor() {
        this.watchers = [];
    }
    add(watcher) {
        this.watchers.push(watcher);
    }
    notify(value) {
        this.watchers.forEach(watcher = >watcher.update(value)); }}// An instruction class Watcher is used to bind update functions to update DOM elements
class Watcher {
    constructor(node, type) {
        this.node = node;
        this.type = type;
    }
    update(value) {
        // Change value for input
        if (this.type == 'input') {
            this.node.value = value;
        }
        // Change the value if it is text
        if (this.type == 'text') {
            this.node.nodeValue = value; }}}Copy the code

conclusion

  1. An observe loop data binds the getter and setter
  2. A compile parses the template, loops childNodes, parses the template syntax and directives
  3. A publish subscription model, subscribe in GET, publish in SET, the same as subscribing to a newspaper, publish a newspaper
  4. This. Target is set in the compile phase and the get method is triggered to publish the listener

You see this? Little brother you can really ox X, attention and praise go an encouragement… ❥ (^ _ -)

If you think it’ll help, you might as well

praise

Continue to output these short and effective articles to help you master the most content in the shortest time. After all, who doesn’t like to do it once and for all? ❥ thank you ~ (^ _ -)