⚠️ this article for nuggets community first contract article, not authorized to forbid reprint

preface

Most of the time, we show some desire for source code, but when asked why we want to see source code at all, there are only a few answers:

  • In order to the interview
  • To write their own source code on the resume
  • Understand the underlying principles of master thinking
  • Use the source code to learn some tips (SAO operation)
  • Curious about how the framework implements various functions
  • He who does not advance loses ground
  • Want to build your own wheel and see what other people do first
  • All kinds of public accounts and selling classes are selling anxiety and brainwashed

But very few people actually understand the source code, partly because there is so much code, and partly because it is easy to get confused when reading other people’s code. Because everyone’s coding style and coding habits are very different, it can be tiring to look at the code of someone whose coding habits are different from your own.

Besides, not only do people have different coding styles, but they also have different technical directions and skills. After removing the above reasons, a more important reason is that many people are not proficient enough to use the framework, used API is so few common, other not commonly used but very high level API are not used, even don’t understand, such people look at the source code of course will be confused!

That certain someone will say: yu Yu creek he frame must be used very 6? I use his framework every day to write code, he is not necessarily as skilled as I!

There’s some truth to that, but when it comes to the bottom line, he knows better than anyone. One of the reasons why we don’t chew on the source code is very important: there are too many details, it is easy to make you can’t find the focus. These details of things naturally have their reason to exist, but they have become a stumbling block in the way we walk in the study of source code.

digression

How to learn source code is the most scientific way? Let’s take an example: There are some very high-technology sounding products, such as electromagnetic railguns. Every major military power is vying to explore this field, and suppose one day we wake up and become the national chief researcher for the electromagnetic railgun, which is dedicated to the underlying technology of the electromagnetic railgun. So when we disassemble an electromagnetic railgun, chances are you won’t be able to read the inside of it. Because it will contain a lot of very complex high strength materials, electrodes to control the magnetic force, winding wires, precision devices, user friendly packaging, etc…

At this point, you may not be very easy to understand the real principle of electromagnetic railgun, until one time on the Internet came across a video, the video of people using some magnets, some steel balls, and a few materials we can get in daily life to make a simple version of the electromagnetic railgun. We were able to figure out how railguns really work, and it wasn’t really practical, but once we understood the basics, we were able to build on them, and we were able to figure out how to build a complex railgun that could be used in combat.

Source code is the same, we in accordance with the electromagnetic railgun idea step by step, first make clear the core of the basic part, slowly and then step by step to advance. This is a much better way to learn than we would surely have to disassemble a full version of the railgun

Since we had such a need, as the author of a popular framework, it was inevitable that we would respond: in the course of a training session, Yu Yuxi led the group to write a very miniature Vue3. But it is a pity that this is a one-day training he has done abroad, and our domestic audience is not blessed to be able to enjoy such a teaching training by the frame writer. But fortunately, You yuxi has uploaded all the code to Codepen, you can click on this link to read the code written by you Yuxi, or you can choose to stay in this article, see me in Chinese to explain you Yuxi’s own code!

Responsive article

Yu Yuxi in a live broadcast has said: Vue3 source code than THE source of Vue2 to learn a lot. Vue3 is better than Vue2 in terms of architecture and module coupling design, which can be seen module by module so that it is easier to understand. If you’re new to the game, start with Reactivity. Because Reactivity is a module in the entire Vue3 without any external coupling.

‘Reactivity’ is a form of response. ‘React’ is also known as’ React ‘. So what is the response? Think about it. What’s the framework of React? The MVVM, right? The main slogan of MVVM is:

Data-driven view!

This means that when the data changes, we will render the components again, so that when we change the data, the place on the page where the data is used will change in real time. But you can do more than just update your view when your data changes! When yuyuxi created the @vue/reactivity module, it borrowed from the @nx-js/observer-util library. Let’s take a look at this sample code shown on GitHub’s readme.md:

import { observable, observe } from '@nx-js/observer-util';

const counter = observable({ num: 0 });
const countLogger = observe(() = > console.log(counter.num));

// This line of code will call countLogger and print: 1
counter.num++;
Copy the code

It’s like Vue3’s reactive and watchEffect. In fact, we define a function in advance, when the dependent data item in the function changes the function will automatically execute this function, this is the response!

Data-driven views make it easier to understand why a function can perform a function that updates the view when the data changes:

import { store, view } from 'react-easy-state';

const counter = store({
  num: 0.up() {
    this.num++; }});// This is a responsive component that automatically rerenders the component when counter. Num changes
const UserComp = view(() = > <div onClick={counter.up}>{counter.num}</div>);
Copy the code

React-easy-state is a function that encapsulates the react function. View is a variation of Observe. Observe requires you to pass in a function that executes whatever you want. The view requires you to upload a component to it. When data changes, the view performs an update logic written in advance. This is the same as when you write an update to the view. I’m writing React with this library just like I’m writing Vue.

The source code

After understanding what is the response type can be convenient for us to look at the source code, to see how yu Yu Creek is only a dozen lines of code to achieve the response type:

let activeEffect

class Dep {
  subscribers = new Set(a)depend() {
    if (activeEffect) {
      this.subscribers.add(activeEffect)
    }
  }
  notify() {
    this.subscribers.forEach(effect= > effect())
  }
}

function watchEffect(effect) {
  activeEffect = effect
  effect()
}
Copy the code

Let’s see how to use it:

const dep = new Dep()

let actualCount = 0
const state = {
  get count() {
    dep.depend()
    return actualCount
  },
  set count(newCount) {
    actualCount = newCount
    dep.notify()
  }
}

watchEffect(() = > {
  console.log(state.count)
}) / / 0

state.count++ / / 1
Copy the code

If you can’t look at a dozen or twenty lines of code without feeling convoluted, then you’re on a bad base. Because it’s easy to see at a glance that this is a very classic design pattern: publish and subscribe

Publish and subscribe

If you’re not familiar with the publis-subscribe model, we can talk about it briefly. However, if you are familiar with these design patterns and can easily read the code you just wrote, it is advisable to skip this section for now.

In the book JavaScript Design Patterns and Development Practices, the authors explore a very vivid example of the publis-subscribe model:

Xiao Ming recently had his eye on a house, only to be told at the sales office that the building had already been sold out. Fortunately, sales MM told Xiaoming that soon there will be some late launch, developers are dealing with the relevant procedures, after the procedures can be bought. When, no one knows yet.

So Xiao Ming took down the phone number of the sales office, and will call every day to ask whether it is time to buy. Besides Xiao Ming, xiao Hong, Xiao Qiang and Xiao Long also consult the sales office every day about this problem. A week later, sales MM decided to resign, because tired of answering the same content of 1000 phone calls every day.

Of course, there is no such stupid sales company in real life. In fact, the story goes that Xiao Ming left his phone number at the sales office before he left. Sales MM promised him, a new building launched immediately send information to notify Xiaoming. Xiao Hong, xiao Qiang and xiao long are the same, their phone numbers are recorded in the sales office roster, when the new building launched, sales MM will open the roster, through the phone number above, sent a text message to inform them in turn.

In the example just mentioned, sending SMS notifications is a typical publis-subscribe model. Buyers like Xiao Ming and Xiao Hong are subscribers, and they subscribe to the news that the house is on sale. The sales office, as the publisher, will go through the phone number on the roster at the right time and release the news to the buyers in turn.

If you’ve ever used the xxx.addEventListener function to add events to the DOM, then you’ve actually used the publish-subscribe mode. Think about this example from the sales office:

  • We need to do something under certain conditions
  • But what we don’t know is when is this going to be true
  • So let’s leave our function
  • Automatically executed when the condition is true

So let’s simply simulate what happens with addEventListener to help you understand the publish-and-subscribe pattern:

class DOM {
    #eventObj = {
        click: [].mouseover: [].mouseout: [].mousemove: [].keydown: [].keyup: []
        // There are many other event types
    }
    addEventListener (event, fn) {
        this.#eventObj[event].push(fn)
    }
    removeEventListener (event, fn) {
        const arr = this.#eventObj[event]
        const index = arr.indexOf(fn)
        arr.splice(index, 1)
    }
    click () {
        this.#eventObj.click.forEach(fn= > fn.apply(this))
    }
    mouseover () {
        this.#eventObj.mouseover.forEach(fn= > fn.apply(this))}// There are many other event methods
}
Copy the code

Let’s try it out:

const dom = new DOM()

dom.addEventListener('click'.() = > console.log('Click! '))
dom.addEventListener('click'.function () { console.log(this) })

dom.addEventListener('mouseover'.() = > console.log('Mouse into! '))
dom.addEventListener('mouseover'.function () { console.log(this)})// Simulate the click event
dom.click() // Print out: 'Click! 'and the corresponding this object

// Simulate mouse events
dom.mouseover() // Print out: 'Mouse in! 'and the corresponding this object

const fn = () = > {}
dom.addEventListener('click', fn)
// You can also remove the listener
dom.removeEventListener('click', fn)
Copy the code

This simple example should make sense of the publish-subscribe pattern, right?

Let’s take a look at the three main points outlined in JavaScript Design Patterns and Development Practices for the publk-subscribe model:

  1. First identify who will act as the publisher (such as the sales office)In this case, it's dom
  2. Then add a cache list to the publisher to hold callbacks to notify subscribers (the sales office roster)In this case, it's dom.#eventObj
  3. At the end of the Posting, the publisher iterates through the list and triggers the subscriber callback function in turn (iterating through the list and texting each message).

With these three points in mind, take a look at a larger piece of code and see if it fits the three points:

  • The publisherObject: the dep
  • Cache list: dep. Subscribers
  • news: dep. Notify ()

So this is a typical publish-subscribe pattern

Enhanced version

The first version of yuyucreek code was a bit too crude to use, because we had to hand-write getters and setters, manually execute dependent collection functions, and trigger functions every time we defined data. This part is obviously going to be able to be encapsulated again, so take a look at the second version of the Yuyuxi implementation:

let activeEffect

class Dep {
  subscribers = new Set(a)depend() {
    if (activeEffect) {
      this.subscribers.add(activeEffect)
    }
  }
  notify() {
    this.subscribers.forEach(effect= > effect())
  }
}

function watchEffect(effect) {
  activeEffect = effect
  effect()
  activeEffect = null
}

function reactive(raw) {
  / / use Object. DefineProperty
  // 1. Iterate over the existing keys on the object
  Object.keys(raw).forEach(key= > {
    // 2. Create a dependency object for each key
    const dep = new Dep()

    // 3. Override the properties of the original object with getters and setters
    let realValue = raw[key]
    Object.defineProperty(raw, key, {
      get() {
        // 4. Call the corresponding method of the dependent object in the getter and setter
        dep.depend()
        return realValue
      },
      set(newValue) {
        realValue = newValue
        dep.notify()
      }
    })
  })
  return raw
}
Copy the code

You can see that the implementation of this version is much better than the last one, and it feels like Yuyuxi has been more careful in writing this version of the code than the last one. Since this version of the code has detailed comments, it must be a carefully explained code. Only the original notes were written in English and I translated them into Chinese.

But you see please rest assured, in addition to the comments I translated into Chinese, other places I did not move a letter, even the space are to maintain the original indented, is to be able to let you see is the yuyu creek first-hand code 😋

As you can see, this version of the code is implemented using two design patterns: the proxy pattern and the publis-subscribe pattern we just talked about. That’s how important it is to learn design patterns well. If you are interested in design patterns, you can go to the B site search front-end learning is not moving, currently in the serialized design patterns, personally feel that moOCs that sell 288 JavaScript design patterns class is more clear.

The proxy pattern

The proxy pattern is relatively simple and does not require any code. Let’s take an interesting example from Xiu Yan, author of JavaScript Design Pattern Core Principles and Application Practices:

I work with a guy with great technique and great hair. For many years, I was addicted to coding and delayed a major event in my life. Forced to find the other half of the desire is more urgent, this colleague is a number of high-quality high-end dating websites registered VIP. In his spare time, he often shares with us the recent progress of his dating life.

“You see, this girl profile picture is not super cute!” My colleague discovered a new matchmaking agency this day. He held up his mobile phone and waved wildly at several people around him.

“Brother, that is niigaki jieyi…” Colleague brother’s deskmate shook his head helplessly, did not stop coding hand.

My colleague recovered his composure and sighed: “The mechanism of this dating platform is so strict that you can only see other members’ names, ages and self-introductions when you come in. In order to see your photo or get contact information, you have to pay to be a VIP. Oh, I’ll buy another VIP.”

I listen to, wow, this matchmaking platform play proxy mode pretty 6! Let’s think about it. The subject is colleague A, and the target is the unknown girl with the picture of Niigaki Jieyi. Colleague A cannot communicate directly with the unknown girl, but can only obtain some information of the other party indirectly through the third party (matchmaking agency). The information and permission he can obtain depends on what the third party is willing to give him — isn’t this A typical agency model?

usage

This version of the response is much more comfortable to use:

const state = reactive({
  count: 0
})

watchEffect(() = > {
  console.log(state.count)
}) / / 0

state.count++ / / 1
Copy the code

It’s basically the same way Vue3 is used! You can see that the core principle of responsiveness is the publis-subscribe + broker pattern. However, this is not the final version, because he used ES5’s Object. DefineProperty to do the Proxy mode, if not considering IE compatibility, ES6 Proxy is more suitable to do the Proxy, because Proxy in translation means Proxy, agent. So Vue3 uses a Proxy to refactor the entire responsive code. Let’s take a look at the final version written by Yuyuxi.

The Proxy version

let activeEffect

class Dep {
  subscribers = new Set(a)constructor(value) {
    this._value = value
  }

  get value() {
    this.depend()
    return this._value
  }

  set value(value) {
    this._value = value
    this.notify()
  }

  depend() {
    if (activeEffect) {
      this.subscribers.add(activeEffect)
    }
  }

  notify() {
    this.subscribers.forEach((effect) = > {
      effect()
    })
  }
}

function watchEffect(effect) {
  activeEffect = effect
  effect()
  activeEffect = null
}

// proxy version
const reactiveHandlers = {
  get(target, key) {
    const value = getDep(target, key).value
    if (value && typeof value === 'object') {
      return reactive(value)
    } else {
      return value
    }
  },
  set(target, key, value) {
    getDep(target, key).value = value
  }
}

const targetToHashMap = new WeakMap(a)function getDep(target, key) {
  let depMap = targetToHashMap.get(target)
  if(! depMap) { depMap =new Map()
    targetToHashMap.set(target, depMap)
  }

  let dep = depMap.get(key)
  if(! dep) { dep =new Dep(target[key])
    depMap.set(key, dep)
  }

  return dep
}

function reactive(obj) {
  return new Proxy(obj, reactiveHandlers)
}
Copy the code

As you can see, the code in this version is a little more complicated than in the previous version, but the usage is exactly the same:

const state = reactive({
  count: 0
})

watchEffect(() = > {
  console.log(state.count)
}) / / 0

state.count++ / / 1
Copy the code

Let’s focus on the final version of the code, which is the best. Even though it is small, it has all the elements in it, not only doing the most basic publish/subscribe + broker model, but also using a lot of small techniques to optimize performance.

Break down

First, you define an empty variable called activeEffect to hold the function that watchEffect passes in:

// Define a variable that temporarily holds the watchEffect passed parameters
let activeEffect
Copy the code

And then I define a class called Dep, which should be short for Dependence. In effect, this is equivalent to the publisher class in the publish-subscribe pattern:

// Define a Dep class that will generate a publisher instance for each key of each responsive object
class Dep {
  // Use Set as the cache list to prevent adding multiple identical functions to the list
  subscribers = new Set(a)// The constructor accepts an initialized value in a private variable
  constructor(value) {
    this._value = value
  }

  // When the value on an object is obtained using xxx.value
  get value() {
    // Proxy mode triggers the depend method when getting the value of the value attribute on an object
    this.depend()

    // Then return the value in the private variable
    return this._value
  }

  // When the value on an object is changed using xxx.value = XXX
  set value(value) {
    The notify method is triggered when the value attribute on an object is changed
    this._value = value
    // Change the value first and then trigger it to ensure that the new value is used when firing
    this.notify()
  }

  // This is often referred to as dependency collection
  depend() {
    // if the activeEffect variable is null, it indicates that the get operation was not triggered in the watchEffect function
    if (activeEffect) {
      // but if activeEffect is not null, it proves that the get was triggered in the watchEffect
      // add the activeEffect variable with the watchEffect parameter to the cache list
      this.subscribers.add(activeEffect)
    }
  }

  // The update operation is usually called after the value has been changed
  notify() {
    // Iterates through the cache list and triggers execution
    this.subscribers.forEach((effect) = > {
      effect()
    })
  }
}
Copy the code

Whereas the previous two versions mostly defined a variable in the outer header to hold the value of each key of the responsive object, this time we put the value directly into the definition of the Dep class, which defines getters and setters, and relies on collecting the value when it is fetched and updating the value when it is modified.

We then define a function with the same name as Vue3’s watchEffect:

// Imitate the watchEffect function of Vue3
function watchEffect(effect) {
  // put the passed function into the activeEffect variable
  activeEffect = effect

  // Then execute the watchEffect function
  effect()

  // finally set activeEffect to null
  activeEffect = null
}
Copy the code

When we use this function, we will pass in another function:

watchEffect(() = > state.xxx)
Copy the code

The function is assigned to the activeEffect variable, and then it executes the function right away, and it usually has some reactive object in it, right? If so, it triggers a getter to do a dependency collection, which determines if the activeEffect variable has a value, and if so, adds it to the cache list. Immediately after executing the function, set the activeEffect variable to null to prevent dependency collection from happening when the getter is not triggered in the watchEffect function.

The next step is to define a Proxy to handle objects:

const reactiveHandlers = {
  // When the get operation is triggered
  get(target, key) {
    // Call getDep to fetch the value stored in it
    const value = getDep(target, key).value

    // If value is an object
    if (value && typeof value === 'object') {
      // Then make value a reactive object
      return reactive(value)
    } else {
      // Return the value directly if it is a basic data type
      return value
    }
  },
  // When the set operation is triggered
  set(target, key, value) {
    // Call getDep and reassign the value to the value of the set operation
    getDep(target, key).value = value
  }
}
Copy the code

If you are not very familiar with Proxy, it is recommended to have a look at Ruan Yifeng’s “ES6 Introduction Tutorial”, written or good.

GetDep () ¶ getDep (); getDep (); targetToHashMap (); targetToHashMap ();

// Define a WeakMap data type to store the objects defined by reactive and their publisher object set
const targetToHashMap = new WeakMap(a)Copy the code

Let’s define the getDep function:

GetDep getDep getDep getDep getDep getDep getDep getDep getDep getDep getDep getDep getDep getDep
function getDep(target, key) {
  // Get the publisher object set of reactive objects. Reactive objects
  let depMap = targetToHashMap.get(target)

  // If not
  if(! depMap) {// Create an empty publisher object set
    depMap = new Map(a)// Then save the publisher object collection into the WeakMap
    targetToHashMap.set(target, depMap)
  }

  // Then get the publisher object corresponding to a key in the publisher object set
  let dep = depMap.get(key)

  // If not
  if(! dep) {// Create a new publisher object and initialize the assignment
    dep = new Dep(target[key])
    // Then put the publisher object into the publisher object set
    depMap.set(key, dep)
  }

  // Finally return the publisher object
  return dep
}
Copy the code

This is where it gets a little convoluted. Let’s look at the image above:

Every object passed into reactive will be stored on the key in the WeakMap. The value of each key is a Map:

                                    // targetToHashMap: {
const obj1 = reactive({ num: 1 })   // { num: 1 }: new Map(),
const obj2 = reactive({ num: 2 })   // { num: 2 }: new Map(),
const obj3 = reactive({ num: 3 })   // { num: 3 }: new Map()
                                    / /}
Copy the code

So what’s in the Map? Deposit is:

Reactive object {a: 0, b: 1, C: 2}

{
  'a': new Dep(0),
  'b': new Dep(1),
  'c': new Dep(2)}Copy the code

Put the object’s key on the Map’s key, create a publisher object with new Dep, and pass the value to the Dep. One of the most important optimization points of Vue3’s performance over Vue2 is this Proxy. This is not to say that the performance of Proxy is much better than that of object.defineProperty, but that the handling in Proxy is much better than that in Vue2: The response of Vue2 is to iterate + recursion to make all the data you define reactive, which will cause pages written in Vue2 to be blank for a short period of time if there are a lot of complex data structures on the page. After all, traversal + recursion is a relatively slow operation!

React doesn’t have this problem, and Vue3 certainly doesn’t have this problem. As you can see from the code, when we obtain the value of a key on an object, we first determine whether the value corresponds to a publisher object, and then create a publisher object. When the obtained value is of a reference type, it will be converted to a reactive object, and when the value in the reactive object is used, it will create a publisher object.

To sum up, Vue3 is to use which part of the data, and then the data into a responsive. Vue2, on the other hand, gives you responsive data at the beginning of the game.

The final step is to define the reactive function:

// Imitate Vue3's reactive function
function reactive(obj) {
  // Return a proxy object for the passed parameter object so that operations on the object are intercepted using the proxy pattern and the publish-subscribe pattern is applied
  return new Proxy(obj, reactiveHandlers)
}
Copy the code

The flow chart

In order to facilitate everybody understanding, we use the reactive and again watchEffect function, and then see what happens:

First we define an object {num: 0} with reactive function. This object will be passed to the Proxy as the first argument, and nothing has happened yet. So let’s print the num property of this object in watchEffect:

The function passed to watchEffect is assigned to the actibveEffect variable and is immediately executed:

In the process of execution, a get operation is found, so it is intercepted by the Proxy, and it goes to the step of GET:

GetDep ({num: 0}, ‘num’); getDep({num: 0}, ‘num’); When you enter getDep, you need to use the targetToHashMap to get the value of the {num: 0} key, but currently the targetToHashMap is empty, so you don’t get anything at all. Targettohashmap.set ({num: 0}, new Map());

The Map is empty, so we can’t get the value, so we create a new Dep object:

Since getDep(… XXX).value to get the value property of this object, so the getter is fired:

Following the getter, we come to the depend method. Since the activeEffect has a value, we enter the judgment and add the activeEffect to the Set structure of subscribes. Let’s change the value of obj.num and see what happens:

First, the Proxy intercepts the set operation and then calls getDep:

When we get the DEP object, we change its value property, triggering the setter:

Finally, we come to the notify phase, and in the notification phase we find our cache list (subscribers) and fire all the functions in it:

If () => console.log(obj.num) => console.log(obj.num) Of course not! Because the obj. Num operation is running, it triggers the get operation to be intercepted by Proxy:

When we get the publisher object we created earlier, we trigger the getter action on the publisher object:

We need to check the activeEffect variable when we go to depend:

Since it doesn’t go into the judgment, it executes a lonely (nothing executes), so the following code is:

The final print was 10.

conclusion

I didn’t think 70 lines of code would work that way, did I? That’s how important it is to learn in a piece-by-piece way. If you look directly at the source code, there will certainly be a variety of judgments. For example, watchEffect doesn’t make any judgments right now, right? So what happens when we pass watchEffect an argument that’s not a function? What happens when we pass an array to reactive? What about when we pass Map and Set? What about the basic data types? And even if we don’t think about that right now, if we just pass an object, no array or anything else in it, watchEffect just passes the function. There is a difference in the watchEffect experience from Vue3, which is that you cannot change the value of a reactive object in the watchEffect:

It’s not a problem to write it like this:

This is not the case with watchEffect in Vue3. This is because if you assign to a reactive object in a watchEffect it triggers a set operation, which is intercepted by the Proxy, and then goes to the notify method, which runs the watchEffect function again, The notify method is run again, and the set operation is triggered again.

So we still need to consider the infinite loop situation, but if we really consider so comprehensive, I believe that the amount of code is quite large, we will be further confused. So get through the code, and then slowly we’ll see how the real source code handles these situations. Or you can not look at the source code, think about how to deal with these problems, and then write their own logic to test no problem and then go to Vue3 source comparison, see their own implementation and yu Yu Creek implementation of the way there are similarities and differences.

This is the end of this article, but not yet. This is just the response part. Then there are virtual DOM, diff algorithm, componentization, root component mounting and other parts.

If you can’t wait for the next parsing article, you can also click on this link to go to Codepen and dig into yuyuxi’s code for yourself. It’s a small amount of code, so it’s a great way to learn how Vue3 works! After learning the principle even if not to see the real source code, when the interview can be with the interviewer blow two sentences. Because after all, no interviewer is going to look at the source code and ask: What does line 996 of the Vue3 file say? The investigation certainly focuses on the principle, and rarely examines the boundary case processing of various judgment parameters. So like + attention, follow yuyuxi study source code don’t get lost!

Previous excellent article

  • Product Manager: Can we roll the numbers?
  • “Product Manager: The opening animation of Hongmeng is very handsome. Please give us a whole page.”
  • Create your own Visual Data Map without any libraries
  • Vue3 will not support IE11, but focus on Vue2.7
  • A fun new feature of Vue: Introducing JS variables into CSS
  • What? Can you pull and pull with just the H5 TAB?
  • Microsoft launches comments section on GitHub
  • Vue 3.0.3: New CSS variable passing and the latest Ref Proposal
  • “Double 11 small black box is cool? Let’s use CSS variables to improve!”
  • “Don’t underestimate the nine grid, one question can let a candidate reveal his true colors!”
  • “Mobile Layout Interview Questions to test your CSS Skills (Center)”
  • A series of confusing behaviors after setting prototype Objects as Proxies
  • Vue’s Super Fun New Feature: DOM Portal
  • “Use of React’s Super-popular CSS-in-JS Library in the Vue Project: Styled – Components”
  • Is It Finally Vue’s Turn to Inspire React?
  • A Small Pit in Vue3 on IOS
  • Hooks use of the New VUe-Router
  • Yu Yuxi: The Design Process of Vue3
  • The Father of Node’s refactoring Deno is finally released. Will it Replace Node after all?