Please don’t stop to be the person you want to be

Don’t loop through arrays of 1-1000

Array.from({length:1000},(x,y)= >y+1)

Copy the code

CSS Performance Optimization

1.Merge CSS, (because loading3a1KB of CSS is better than loading one100KB CSS is slower)

2.Do not use @import which will affect the current CSS loading speed

3.Avoid CSS hierarchies too deep (best3Level of less than)

4.Remove common styles so that part of the CSS can be cached (this will speed up the first CSS load, depending)

5.Use CSS inheritance care (for example, the parent has color, font, so do not define the child color, font)

6.Use Sprite image cssSprite (combine multiple images into one image so we can reduce image requests)

7.Compress the CSS

Copy the code

Talk about inheritance and the difference between ES5 and ES6 inheritance?

// Es5 inherits the static method of the current method through the prototype chain, and calls the constructor of the parent component with call or apply

/ / es5 inheritance

var fn = function(name){

    this.name = name

}

fn.prototype.xname = 'Joe' 

var x = function(name){

    fn.call(this,name)

}

x.prototype = fn.prototype

x.prototype.constructor = fn

var y = new x('Ming')

// {name:' xiaoming '} // __proto__ has the current xname attribute as' Zhang Three '.



// ES6 extends the fn component's methods via the extends keyword, using super to call the parent component's constructor

class fn{

    constructor(name){

        this.name = name

        this.xname = 'Joe'

    }

}

class x extends fn{

    // Super must be added to perform the parent component's constructor so that the child component gets the assignment of the current name

    constructor(name){

        super(name)

    }

}

let y = new x('Joe')

// {name:' xiaoming ',xname:' Zhangsan '}

Copy the code

Implement fn(1)(2)(3) = 6 and add after it for infinite extension

// It is used now

// 1 return f (Function) so that the method can be used indefinitely

// 2 uses toString and valueOf to call toString and valueOf when no value is retrieved.

// 3 Val is a closure. The current val is always called by f, so it is never collected by garbage collection

let fn = function(x){

    let val = x

    let f = function(y){

        val += y

        return f

    }

    f.toString = function(){

        return val + ' '

    }

    f.valueOf = function(){

        return val

    }

    return f

}

fn(1) (2) (3/ / 6

Copy the code

Vue2. X implementation principle

// Hijacking the current object via defineProperty for bidirectional binding

// defineProperty Cannot hijack an array requires a special pair operation

let ArrayPro = Array.prototype

let ArrayObj = Object.create(ArrayPro);

['pop'.'push'.'splice'.'shift'.'onshift'].forEach(item= >{

    ArrayObj[item] = function(){

        updataView()

        ArrayPro[item].call(this. arguments)

    }

})

// Update the view

function updateView(){

    console.log('Update view')

}



let reactProperty = function(obj,item,val){

    // Recursively listen down. Defineproperty can only listen on one level

    observer(val)

    Object.defineProperty(obj,item,{

        get(){

            return val

        },

        set(newVal){

            if(newVal! ==val){

                val = newVal

                updateView()

            }

        }

    })

}



let observer = function(obj){

    // Null equals Typeof Object for historical reasons

    if(typeofobj ! = ='object' || obj === null) {

        return 

    }

    / / ArrayObj: 'pop' and 'push', 'splice', 'shift' and 'onshift'

    // Objects with these methods call the array's own methods when executed

    // The current array case will point to the current ArrayObj so that our array can be listened on

    if(Array.isArray(obj)){

        obj.__proto__ = ArrayObj

    }

    for(let item in obj){

        // Check that the current data is in obj

        if(obj.hasOwnProperty(item)){

            reactProperty(obj,item,obj[item])

        }

    }

}



let objectA = {

    a1.

    v: []

}

observer(objectA)

objectA.a = 2

objectA.v.push(1)

Copy the code

How to deal with the DIFF algorithm in vue.js?

1.Only the same level is compared

2.Replace the current tag (DOM) directly

3.The currentkeyAs with tag, no comparison is made

Copy the code

What is the time complexity of the DIFF algorithm in vue.js? Why is that?

The new vDOM is compared to the old vDOM, so the complexity is O(n2), and then you have to change it (add or delete it), so it's O(n3).

Copy the code

What periodic functions are available in vue.js? When are these periodic functions executed?

1.beforeCreate / / prior to the start

2.Creaed / /

// Determine the current template or render function

3.bedoreMount // Before dom creation

4.Mounted // After dom creation (mount complete)

// beforeUpdate // beforeUpdate

// Updated // DOM rendering is complete

5.beforeDestroy / / before destruction

6.Destroyed / / after destruction



// Parent component nesting lifecycle

1.Father beforeCreate

2.The father Created

3.Father beforeMount

4.The child beforeCreate

5.Son of the Create

6.The child beforeMount

7.The child Mounted

8.Father Mounted



// Parent component destruction

1.Father beforeDestroy

2.The child beforeDestroy

3.The child Destroyed

4.Father is Destroyed



// Parent component updates

1.Father beforeUpate

2.The child beforeUpate

3.The child Upated

4.Father Upated

Copy the code

What is MVC? The MVVM?

// MVC from text we can derive model, view, controller when we click a button

(View) passes the click event, the controller (logic) (Controller) assigns values to a field (model and data (variables)),

When we change the data, we render the DOM of the current view

// MVVM m (model) v (View) VM (VUE control, view module (abstract view))

MVVM is data change view, when our data changes, we modify our view through vUE (VM), and then the view changes through (VM).

To modify our model

Copy the code

Observer versus publish/subscribe?

// A brief introduction of the two modes

Observer mode is for example, you and Xiao Ming both want to drink milk, and then call the milk station. The staff of the milk station will deliver such a pattern to you

This is the observer mode, and the subscription mode is that you call the milk station agent, not directly contact with the milk station, the milk station only need to deliver goods to the agent

Yes, and all you have to do is contact the agent, and then the milk station will be connected instead of having to deal with delivery and all that kind of stuff by subscription publishing.



// Observer mode

/ / xiao Ming

let subject = function(name){

    this.name = name

}

subject.prototype.go = function(){

    console.log(`The ${this.name}Sour sweet really good to drink ')

}

/ / service station

let observer = function(name){

    this.name = name

    this.list = []

}

observer.prototype.push = function(obj){

    this.list.push(obj)

}

observer.prototype.go = function(){

    this.list.forEach(item= >{

        item.go()

    })

}

let server = new observer('Milk Station')

// Xiaoming subscribs milk

server.push(new subject('Ming'))

// Xiao Hong subscribs milk

server.push(new subject('little red'))

// The milk station distributes milk

server.go()

// I will write the following comments here for the ES6 version, but almost



// Publish a subscription

/ / agent

let subject = function(name){

    this.name = name

}

subject.prototype.go = function(min){

    console.log(`${min}Sour sweet really good to drink ')

}

let pubSub = function(){

    this.fnList = {}

}

pubSub.prototype.push = function(type, fn){

    this.fnList[type] = fn

}

pubSub.prototype.go = function(type){

    let fn = this.fnList[type]

    fn.call(this. arguments)

}

let pub = new pubSub()

let min = new subject('Ming')

pub.push('min',min.go)

pub.go('min')

Copy the code

The difference between an arrow function and a normal function

1The arrow function this points to this that does not always point to the context because of the call, apply, bind impression. Ordinary functions point to the caller

2Arrow functions have no arguments with (... Rest) = >{}Instead, arrow functions are anonymous

3Arrow functions have no prototypeconstructor

Copy the code

Detailed process from entering url to page presentation

1. Enter the url

2.dnsparsing

3. Establishtcplink

4. The client sends a request

5. The server processes the request

6. The server returns data

7. The client receives data

8. Client displayhtml

9. The client sends a requesthtmlResources needed inside (img.js.css)

10. (domTrees andstyleRules)renderThe tree is then rendered

Copy the code

HTTPS implementation principles (the more detailed, the better)

1. The client sends a request to the server (port 443) (HTTP port 80).

2. The server returns the current digital certificate and public key

3. The client verifies the digital certificate, generates a random number, generates a symmetric encryption key with the public key, and sends the key to the server

4. The server parses the secret key to obtain a random number, encrypts the data to be transmitted through symmetric encryption, and sends it to the client

5. The client parses the encrypted data to obtain the data

Copy the code
HTTPS Implementation Principle

Page rendering process

1.Generate a dom tree

2.Generate CSS Rules

3.Loading js will affect our generation 👆 (it will clog the page so try to put it last)

3.Generate our render tree

4.Render our page

5.Redraw and backflow (backflow costs more than painting)

// Redraw: the page structure is unchanged, such as color, font size

// backflow: dom structure changes must trigger redrawing, such as display: node, which changes the page structure

Copy the code

How to optimize performance (the problem is big and we stratify)

Write the code

We use closures as little as possible

Avoid the use ofwithstatements

Code loop optimization

Use innerHTML for faster performance

Merging DOM operations

modular



When loading

Combination of CSS

Use Sprite (load10zhang1K pictures are better than loading1zhang100K is slower.)

Use CNDS

Lazy loading

Use the cache

Using lazy loading

Put back the script



The overall idea is to reduce the number of requests, reduce CPU usage, and use more local caching

Copy the code

Understanding of front-end modularity

Module is mainly divide and conquer, reuse and decouple, which is beneficial to our development.

There are two principles for how to extract our modules

1: The first one is reuse, reducing unnecessary duplication of code.

2: is a relatively independent module. How to understand? This means that if you write a music player component, you can use it in one place, but this one is relatively independent

Functional independence and no adhesion to other components,

When using components, we should define more default parameters (see business).

Copy the code

What would you say if you were given a project to start from scratch

1. Review the requirements first to see whether there are any loopholes in the requirements and whether they are reasonable

2. Requirements breakdown (assessment time) (some will look at test cases first)

3. Write documents for front-end negotiation (if you have time, try to draw a UML class diagram)

4. Allocate demand (get started)

5. Complete (self-test, unit test)

6. Test measurement

7. Project launch

8. Walk online

Copy the code

The difference between defer and async properties in the Script tag

1.asyncThat's asynchronous loading

2.deferSo load it first and don't execute it, wait until all the elements are parsed,DOMContentLoadedBefore the event triggers execution

Copy the code

Write a bind

First let's consider that bind returns afunctionthenthisPoint to incomingobj

First of all, let's pick oneobj

let obj = 
{

    name : 'Joe'

}

Function.prototype.myBind = function(){

    // Get all the values we passed

    let arr = [...arguments]

    // Get the first object

    let obj = arr.shift()

    // Go to the current method

    let _this = this

    // bind is a method for return

    return function(){

        // This refers to the obj we passed in, followed by some of our arguments

        _this.apply(obj,[...arr,...arguments])

    }

}

/ / use

function name(name){

    console.log(name)

    this.name = name

}

name.myBind(obj,obj.name)()

Copy the code

Write a call

First let's consider that some calls pass in a bunch of values (obj,x,x,x,x,x,x,x,x,x,x,x) and are executed directly

let obj = {

    name'Joe'

}

Function.prototype.myCall = function(){

    let arr = [...arguments]

    // If there is no current input, then it is window

    let obj = arr.shift() || window

    // Assign to fn so that we can assign our this pointer

    obj.fn = this

    / / execution

obj.fn(... arr)

    delete obj.fn

}

/ / execution

function name(name){

    console.log(this)

    console.log([...arguments])

    this.name = name

}

name.myCall(obj,obj.name,1.2.3.4.5)

Copy the code

Handwritten apply

The difference between apply and call is that the values passed in are arrays

let obj = {

    name'Joe'

}

Function.prototype.myApply = function(){

    let arr = [...arguments]

    let obj = arr.shift() || window

    obj.fn = this

    obj.fn([...arr])

    delete obj.fn

}

/ / execution

function name(name){

    console.log(this)

    console.log(name)

}

name.myApply(obj,obj.name,1.2.3.4.5)

Copy the code

Handwritten map and Filter

function map(arr,fun) {

    let ar = []

    for(let i=0; i<arr.length; i++){

        ar.push(fun(arr[i],i,arr))

    }

    return ar

}

map([1.2.3.4.5],(item,index)=>{return item+index})

/ /,3,5,7,9 [1]



function filter(arr,fun) {

     let ar = []

    for(let i=0; i<arr.length; i++){

        if(fun(arr[i],i,arr)) {

            ar.push(arr[i])

        }

    }

    return ar

}

filter([1.2.3.4.5],(item)=>item>2)

/ / / three, four, five

Copy the code

Handwritten ajax

let ajax = new XMLHttpRequest()

ajax.open('get'.'www.xxx.xx/xxx'.false)

ajax.onreadystatechange = function(){

    if (ajax.readystate == 4) {

        // The response content is parsed and can be invoked on the client

        if (ajax.status == 200) {

            // The client request succeeded

            alert(ajax.responseText);

        }

    }

}

ajax.send()

Copy the code

Promise limits the number of concurrent requests

// Promise limits the number of concurrent requests, such as a maximum of 10 interfaces requested by the applets, then the eleventh request must wait until the tenth one is finished before the request can be made, and we pass

// Promise to implement

class limitPromise{

    constructor(max){

        // Maximum number of requests

        this._max = max

        // The current number of requests

        this._count = 0

        // Request tasks currently exceeded

        this._tasklist= []

    }

    // fn The current request function args the current request parameters

call(fn,... args){

        return new Promise((resolve,reject) = >{

            let task = this._createTask(fn,args,resolve,reject)

            if(this._count>=this._max){

                this._tasklist.push(task)

            }else{

                task()

            }

        })

    }

    // Create a task

    _createTask(fn,args,resolve,reject){

        return (a)= >{

fn(... args)

                .then(resolve)

                .catch(reject)

                .finally(_= >{

                    this._count--

                    if(this._tasklist.length){

                        let task = this._tasklist.shift()

                        task()

                    }

                })

            this._count++

        }

    }

}



let limit = new limitPromise(2)



// I am a request

let fn = function(){

    xxxx

}



let ajax = (data) = >{

    limit._call(fn,data)

}

Copy the code

Shallow copy

Shallow copy is to copy only the first layer of data

let obj = {

    a1.

    b2.

    arr: [1, {a1},1[1]]]

}

/ / 1

let obj = Object.assign({},obj)

/ / 2

let fn = (obj) = >{

    let ob = {}

    for(let item in obj){

        if(obj.hasOwnProperty(item)){

            ob[item] = obj[item]

        }

    }

    return ob

}

fn(obj)

Copy the code

Deep copy

Deep copy is a copy of all current layers

let obj = {

    a: 1,

    b: 2,

    arr: [1,{a: 1},[1,[1]]]

}

// Convert string and then convert JSON

// This is problematic, and our funciton Symbol and others do not support it

let obj1 = JSON.pase(JSON.stringify(obj))



// So we can only recurse (object, array)



let obj = {

    a: 1,

    b: 2,

    arr: [1,{a: 1},[1,[1]]]

}



let clone = (obj)=>{

    let val

    let type = Object.prototype.toString.call(obj)

    if(type= = ='[object Object]') {

        val = {}

    }else if(type= = ='[object Array]') {

        val = []

    }else{

        return obj

    }

    for(let item in obj){

        let value = obj[item]

        let type = Object.prototype.toString.call(obj)

        if(type= = ='[object Object]'||type= = ='[object Array]') {

            val[item] = clone(value)

        }else{

            val[item] = value

        }

    }

    return val

}

clone(obj)

Copy the code

Write a pomise

function myPromise(fn){

    this.state = 'pending'

    this.value = ' '

    this.error = ' '

    this.onResolveFn = []

    this.onResjectFun = []

    let resolve = (value) = >{

        if(this.state==='pending') {

            this.state = 'resolved'

            this.value = value

            this.onResolveFn.forEach(fn= >fn(value))

        }

    }

    let resject = (error) = >{

        if(this.state==='pending') {

            this.state = 'resjected'

            this.error = error

            this.onResjectFun.forEach(fn= >fn(error))

        }

    }

    fn(resolve,resject)

}

myPromise.prototype.then = function(resolveFn,resjectFun){

    / / asynchronous

    if(this.state==='pending') {

        if(typeof resolveFn ==='function') {

            this.onResolveFn.push(resolveFn)

        }

        if(typeof resjectFun ==='function') {

            this.onResjectFun.push(resjectFun)

        }

    }

    / / synchronize

    if(this.state==='resolved') {

        if(typeof resolveFn ==='function') {

            resolveFn(this.value)

        }

    }

    if(this.state==='resjected') {

        if(typeof resjectFun ==='function') {

            resjectFun(this.error)

        }

    }

}

let promise1 = new myPromise((resolve,resject) = >{

    resolve(1)

}).then(res= >{

    console.log(res)

})

let promise2 = new myPromise((resolve,resject) = >{

    setTimeout(function(){

        resolve(2)

    },2000)

})

promise2.then(res= >{

    console.log(res)

})

Copy the code

Image stabilization

Anti-shake means that you can do it once in a certain amount of time, and there are two versions where you do it first, and then how long it takes to click again. The other is delayed execution

let dob = function(){

    let arr = [...arguments]

    let fn = arr.shift()

    let time = arr.shift()||1000

    let timeout = null

    // Delay execution

    return function(){

        let that = this

        if(timeout){

            clearTimeout(timeout)

        }

        timeout = setTimeout(function(){

            // The execution can be delayed until the timer ends

            fn.apply(that,[...arr])

        },time)

    }

    // Execute immediately

    return function(){

        if(timeout){

            clearTimeout(timeout)

        }

        // Show is true only when null is present

        letshow = ! timeout

        timeout = setTimeout(function(){

            timeout = null

        },time)

        // There is no need to put the current execution method in the timer

        // So show is true at the beginning, so execute immediately, false at the second click, and only when time has passed

        if(show){

            fn.apply(this,[...arr])

        }

    }

}

Copy the code

The throttle

Throttling is performed only once in a certain period of time and does not overwrite previous ones. There are two kinds, one is to use time, the other is to use timer

let thr = function(){

     let arr = [...arguments]

    let fn = arr.shift()

    let time = arr.shift()||1000

    / / time

    let oldDate = 0

    return function(){

        let newDate = Date.now()

        if(newDate>oldDate+time){

            oldDate = newDate

            fn.apply(this,[...arguments,...arr])

        }

    }

    / / timer

    let show = true

    return function(){

        let context = this

        let arg = [...arguments]

        if(show){

            show = false

            setTimeout(function(){

                show = true

                fn.apply(context,[...arg,...arr])

            },time)

        }

    }

}

Copy the code

V – model principle

The V-Model principle is that VUE helped us build in a short version of $EMIT

/ / the parent component

<xxx v-model='message'></xxx>

// js

export default{

.

    data(){

        return{

            message: 1

        }

    }

}

/ / child component

<template>

    <div @click='$emit('input',value+1)'>

        {{value}}

    </div>

</template>

<script>

    export default{

        props:['value']

    }

</script>

// Vue has built in @input and value equal to the value of model

// The default is

export default{

    model: {

        prop: 'value'.

        event: 'input'

    },

    props:['value']

}



Or let's change the values on this side

<template>

    <div @click="$emit('click',value1+1)">

        {{value1}}

    </div>

</template>

<script>

    export default{

        model: {

            // Define the current value

            prop: 'value1'.

            // Defines the event for the current return

            event: 'click'

        },

        props:['value1']

    }

</script>

// I suggest you try it. Self-feeding

Copy the code

Implicit conversion

/ / add

1+'1' / / 11

1+'true' // 1true

1+true // 2 1+Number(true)

1+undefinede // NaN equals 1+Number(undefinede)

1+null // 1 1+Number(null)

/ / contrast

"2">10 // false Number(2)>10

"2">"10" // true converts to character comparison

"abc">"b" // false is converted to characters for comparison

! [] = =0 // true ! [] returns false. False compares to 0, so it is true

[] = =0 // true [] calls valueOf and toString to get an empty string and then compares both with 0 to false so it is true

[] = =! []// true one is false and the other is an empty string so it is true

[] = = []// false Two reference types are compared to the stack, so false

{} = =! {}// false {} valueOf and toString get [object object]! {} is false so the two are inconsistent

= = {} {}// Two reference type comparisons compare the current stack



var a = ?

if(a==1&&a==2&&a==3) {

    console.log(What is a equal to?)

}



a = {

    value0.

    toString: function(){

        return ++a.value

    }

}

// Objec calls valueOf or toString methods before comparison

Copy the code

Rebuild teacher chenhongdong’s MVVM

1.Example Add listening to an array

2.Observe Monitors data

3.Publish subscription model Dep Watch

4.The form of a computed

5.compile

6.mounted



let ArrayProtoType       = Array.prototype;

let arrayProtoTypeObject = Object.create(ArrayProtoType);

['pop'.'push'.'onshift'.'shift'.'splice'].forEach(item= >{

    // Add an array to obj

    arrayProtoTypeObject[item] = function({

        ArrayProtoType[item].call(this. arguments)

    }

})

const reactProperty = function(obj,item,value{

    let dep = new Dep()

    // Listen recursively

    observer(value)

    Object.defineProperty(obj,item,{

        get(){

            Dep.target && dep.addSub(Dep.target)

            return value

        },

        set(newVal){

            // You can change the value only when the value is different

            if(newVal! ==value){

                value = newVal

                // We add the listener again when the value is changed

                observer(value)

                dep.notity()

            }

        }

    })

}



// Publish a subscription

const Dep = function ({

    this.subs = []

}

Dep.prototype = {

    addSub(sub){

        this.subs.push(sub)

    },

    notity(){

        this.subs.forEach((sub) = >sub.update())

    }

}



const Watch = function(vm,reg,fn{

    this.vm    = vm

    this.fn    = fn

    this.reg   = reg

    Dep.target = this

    this.reg.split('. ').reduce(function(x,y){

        return x[y]

    },this.vm)

    Dep.target = null

}

Watch.prototype.update = function({

    let val = this.reg.split('. ').reduce(function(x,y){

        return x[y]

    },this.vm)

    this.fn(val)

}

// Listen for data

const observer = function(obj{

    if(typeofobj! = ='object'||obj === null) {

        return

    }

    if(Array.isArray(obj)){

        // Switch the pointer

        obj.__proto__ = arrayProtoTypeObject

    }

    for(let item in obj){

        reactProperty(obj,item,obj[item])

    }

}

let Mvvm = function(option = {}{

    let data 

    this.$option = option

    this.$el     = option.el

    data         = this._data = option.data

    // Data listener

    observer(data)

    $option.data. X = app.$option.data

    for(let item in data){

        Object.defineProperty(this,item,{

            // It can be deleted

            configurable: true.

            get(){

                return data[item]

            },

            set(val){

                data[item] = val

            }

        })

    }

    initComputed.call(this)

    // Data rendering

    compile(this.$el,this)

    this.$option.mounted.call(this)

}





// Render the template

const compile = function(el,vm{

    // Get the current total DOM

    vm.$el = document.querySelector(el)

    // Create a memory container

    let fragment = document.createDocumentFragment()

    while(child = vm.$el.firstChild){

        // operate on the current DOM memory

        fragment.appendChild(child)

    }

    function replace(fragment){

        // Replace the DOM under the current memory container

        let reg = / \ {\ {(. *?) \}\}/g

        Array.from(fragment.childNodes).forEach(node= >{

            // The current is V-model

            // on the dom attribute

            if(node.nodeType===1) {

                // Get the property on the current DOM

                let nodeAttr = node.attributes

                Array.from(nodeAttr).forEach(attr= >{

                    // The current attribute name is V-model

                    let name = attr.name

                    // The value of the current property is message

                    let value = attr.value

                    if(name.indexOf('v-') >- 1) {

                        // There is currently a v- assignment on the value property

                        // Assign a value to the current Node VM [value] and listen on the MVVM

                        node.value = vm[value]

                    }

                    // Listen on attributes

                    new Watch(vm,value,(newVal)=>{

                        node.value = newVal

                    })

                    // The default value of the v-model method to add input comes from that

                    node.addEventListener('input'.function(event){

                        let newVal = event.target.value

                        / / triggers the set

                        vm[value] = newVal

                    })

                })

            }

            // dom text

            {{}}}

            if(node.nodeType===3) {

                let text = node.textContent

                text.replace(reg,(x,y)=>{

                    // Assign to the case of A.X.X

                    let val = y.split('. ').reduce(function(x,y){

                        return x[y]

                    },vm)

                     // Listen on attributes

                    new Watch(vm,y,(newVal)=>{

                        node.textContent = newVal

                    })

                    node.textContent = val

                })

            }

            // Recursive calls to children of children may have many levels

            if(node&&node.childNodes){

                replace(node)

            }

        })

    }

    replace(fragment)

    vm.$el.appendChild(fragment)

}



const initComputed = function({

    let vm       = this

    let computed = this.$option.computed

    Object.keys(computed).forEach(item= >{

        Object.defineProperty(vm,item,{

            gettypeof computed[item] === 'function'? computed[item]: computed[item].get,

            set(a)= >{}

        })

    })

}



/ / define MVVM

let app = new Mvvm({

    el      : '#app'.

    computed: {

        xx(){

            return this.message

        }

    },

    data: {

        a      : 1.

        message'hello world'

    },

    mounted(){



    }

})

setTimeout(function(){

    app.message = 'jinjinjin'

},2000)

Copy the code

The last

See the end 🙏 thank you, more like on github facing ❤️ is the best for me to encourage, I will try to share some of my own experience and the correct way to eat

Seek to rely on the spectrum push (Beijing area) can leave a message I +. =