Over the past few days, you’ve been learning about some of the new features of Vue-Next (VUE 3.0), especially the use of the new Composition API. Perhaps the most important and core part of the new API is the part that implements responsive functionality. Moreover, the responsive API can be used not only in the Vue-Next environment, but also on its own.

When I read the source code, I saw that Vue-Next was built entirely in TypeScript, so it seems that TS must learn the skill. Here’s vue-Next.

Major architectural improvements and new features planned and implemented by Vue-Next:

  • Using a modular architecture
  • Optimization of tree “Block”
  • More aggressive static Tree reactive power
  • Support the Source map
  • Built-in identifier prefix (also known as “stripWith”)
  • Built-in pretty-printing
  • With the removal of source map and identifier prefixes, the version of the browser that uses Brotli compression is about 10KB thinner

The Runtime is updated in the following ways:

  • Speed up significantly
  • Both Composition and Options apis are supported, as well as Typings
  • Data change detection based on Proxy
  • Support Fragments could
  • Support Portals
  • Support for Suspense W/async setup()

Finally, there are some 2.x features that have not yet been ported, such as:

  • SFC compiler
  • Server side Rendering and SSR rendering

== Currently, IE11 is not supported ==

The source code for Vue-Next (Vue 3.0) is available, but it is not expected to be released until the first quarter of 2020 at the earliest.

Directory profile

There is a directory called Packages in the code repository, which contains the related source functionality implementations of Vue-Next, as shown below.

├─ │ ├─ Compiler-Core# Compiler for all platforms│ ├ ─ ─ the compiler - dom# compilers written for browsers│ ├ ─ ─ reactivity# Data responsive system│ ├ ─ ─ the runtime - core# Virtual DOM renderer, Vue components and various Vue apis│ ├ ─ ─ the runtime - dom# Runtime for the browser. Its capabilities include handling native DOM apis, DOM events, and DOM properties.│ ├ ─ ─ the runtime - test# Runtime written specifically for tests│ ├ ─ ─ server - the renderer# for SSR│ ├ ─ ─ Shared# Help methods│ ├── Archie │ ├─ ch.htm# Build vue Runtime + Compiler
Copy the code
  • Compiler-core: A platform-independent compiler that contains both the extensible base functionality and all platform-independent plug-ins. Exposes the AST and baseCompile API, which turns a string into an AST

  • Compiler-dom: Compiler-core encapsulated for browsers

  • Run-time core: A platform-independent runtime environment. Support for implementation includes virtual DOM renderers, Vue components, and various Vue apis that can be used to define renderers, also available in VUE2

  • Runtime-dom: Runtime for the browser. Its capabilities include handling the native DOM API, DOM events, DOM properties, etc., exposing important Render and createApp methods

    const{ render, createApp } = createRenderer<Node, Element>({ patchProp, ... nodeOps })export { render, createApp }
    Copy the code
  • Run-time -test: A lightweight Runtime written specifically for testing purposes. For example, we exposed the renderToString method, which looks more and more like react

  • Server-renderer: for SSR, not yet implemented.

  • Shared: Does not expose any API, but mainly contains internal help methods that are platform independent.

  • Vue: the “full” version that references the runtime and Compiler directories mentioned above. The entry file code is as follows

    'use strict'
    
    if (process.env.NODE_ENV === 'production') {
      module.exports = require('./dist/vue.cjs.prod.js')}else {
      module.exports = require('./dist/vue.cjs.js')}Copy the code

    So if you want to read the source code, you still need to look at the build process, which is also consistent with VUE2

Review Vue2.0 responsive mechanism – defineProperty

It’s a cliche, intercepting an object, adding set and get methods to the properties of the object, and since the core is defineProperty you need to intercept the methods of the array

Intercepts the object

function observer(target){
  // If it is not an object data type, return it directly
  if(typeoftarget ! = ='object') {return target
  }
  // Redefine the key
  for(let key in target){
    defineReactive(target,key,target[key])
  }
}

function update(){
  console.log('update view')}function defineReactive(obj,key,value){
  observer(value); // It is possible that the object type is multi-level, recursively hijacked
  Object.defineProperty(obj,key,{
    get(){
      // Collect dependencies in the get method
      return value
    },
    set(newVal){
      if(newVal ! == value){ observer(value); update();// Triggers the update in the set method}}})}const obj = {name:'zhuanzhuan'}
observer(obj);

obj.name = 'new-name';
Copy the code
Output: Update viewCopy the code

Array method hijacking

const oldProtoMehtods = Array.prototype
const proto = Object.create(oldProtoMehtods)

function update(){
  console.log('update view')}function defineReactive(obj,key,value){
  observer(value) // It is possible that the object type is multi-level, recursively hijacked
  Object.defineProperty(obj,key,{
    get(){
      // Collect dependencies in the get method
      return value
    },
    set(newVal){
      if(newVal ! == value){ observer(value) update()// Triggers the update in the set method}}})} ['push'.'pop'.'shift'.'unshift'].forEach(method= >{
  Object.defineProperty(proto, method,{
    get(){
      update()
      return oldProtoMehtods[method]
    }
  })
})

function observer(target){
  if(typeoftarget ! = ='object') {return target
  }
  // If it is not an object data type, return it directly
  if(Array.isArray(target)){
    Object.setPrototypeOf(target, proto)
    // Add observr to each item in the array
    for(let i = 0 ; i < target.length; i++){
      observer(target[i])
    }
    return
  }
  // Redefine the key
  for(let key in target){
    defineReactive(target, key, target[key])
  }
}

let obj = {hobby: [{name:'zhuanzhuan'}]}
observer(obj)
// Using the ['push','pop','shift','unshift'] methods, changing the array triggers view updates
obj.hobby.push('walk')
// Changing an object in the array also triggers view updates
obj.hobby[0].name = 'new-name'
console.log(obj.hobby)

Copy the code
Update view update view [{name: [Getter/Setter]},'walk' ]
Copy the code

Object. DefineProperty shortcomings:

  • Unable to listen for array changes
  • Requires deep traversal, wasting memory

Vue-next preparatory knowledge

Whether you’re reading this article or the source code for the Vue-Next responsive module, two things are essential:

  • Proxy: Objects that define custom behavior for basic operations (such as property lookup, assignment, enumeration, function call, etc.). New agent built-in utility classes in ES6.
  • Reflect: is a built-in object that provides a way to intercept JavaScript operations. These methods are the same as those for proxy Handlers. Reflect is not a function object, so it is not constructable. New reflection utility class in ES6

Proxy

let data = [1.2.3]
let p = new Proxy(data, {
  get(target, key) {
    console.log('Get value :', key)
    return target[key]
  },
  set(target, key, value) {
    console.log(Modified value:, key, value)
    target[key] = value
    return true
  }
})

p.push(4)
Copy the code
Output: Obtained value: push Obtained value: length Modified value: 3 4 Modified value: length 4Copy the code

The nice thing about DefineProperty is that both arrays and objects can fire getters and setters directly, but arrays fire twice because they also fire when you get push and when you change length

In addition to better performance, Proxy replacing deineProperty has the following drawbacks, which is why it happensCause of delete:

  1. [Bug Mc-10864] – New or deleted attributes cannot be listened to
  2. Increments and deletions of array elements cannot be listened to

Reflect

let data = [1.2.3]
let p = new Proxy(data, {
  get(target, key) {
    console.log('Get value :', key)
    return Reflect.get(target,key)
  },
  set(target, key, value) {
    console.log(Modified value:, key, value)
    return Reflect.set(target,key, value)
  }
})

p.push(4)
Copy the code
Output: Obtained value: push Obtained value: length Modified value: 3 4 Modified value: length 4Copy the code

Multiple triggering and deep nesting problems

let data = {name: {title:'zhuanzhuan'}}
let p = new Proxy(data, {
  get(target, key) {
    console.log('Get value :', key)
    return Reflect.get(target,key)
  },
  set(target, key, value) {
    console.log(Modified value:, key, value)
    return Reflect.set(target,key, value)
  }
})

p.name.title = 'xx'
Copy the code
Output: Get value: nameCopy the code

We’ll show you how Vue-Next works.

Initialize the project

Rely on project vue.global.js

  1. Clone project

    $ git clone https://github.com/vuejs/vue-next.git
    Copy the code
  2. Edit the file

    $ npm run dev
    Copy the code
  3. Copy files

    After running the above command will generate root [project] / packages/vue/dist/vue. Global. Js file

Rely on @ vue/composition – API

  1. Install the vue – cli

    $ npm install -g @vue/cli
    # OR
    $ yarn global add @vue/cli
    Copy the code
  2. Create a project

    $ vue create my-project
    # OR
    $ vue ui
    Copy the code
  3. Install comcomposition API in your project to experience the new Vue-Next features

    $ npm install @vue/composition-api --save
    # OR
    $ yarn add @vue/composition-api
    Copy the code
  4. Before you can use any of the capabilities provided by the @vue/ comcomposition API, you must first install them through vue.use ()

    import Vue from 'vue'
    import VueCompositionApi from '@vue/composition-api'
    
    Vue.use(VueCompositionApi)
    Copy the code

    After installing the plug-in, you can use the new Composition API to develop components.

Vue – next to try

Copy the code below and run it. Recommended to use a higher version of Chrome, remember to open the F12 debugging tool oh!


      
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="https://s1.zhuanstatic.com/common/js/vue-next-3.0.0-alpha.0.js"></script>
</head>
<body>
<div id='app'></div>
</body>
<script>
  const { createApp, reactive, computed, effect } = Vue;

  const RootComponent = {
    template: '< button@click ="increment"> {{state.name}} {{state.age}} ' < {state.double}} ,
    setup() {
      const state = reactive({
        name: 'walk'.age: 3.double: computed((a)= > state.age * 2)
      })
      
      effect((a)= > {
        console.log('effect' triggers! -${state.name}This year,${state.age}Age. Times 2 is${state.double}`)})function increment() {
        state.age++
      }

      return {
        state,
        increment
      }
    }
  }
  createApp().mount(RootComponent, '#app')
</script>
</html>
Copy the code

Reactive is becoming more like react-hooks. You can go to Composition API RFC to see the details.

  1. Vue-next also supports hand-written render. If both template and render exist, render takes precedence.

  2. The setup option is a major new change. As the name implies, the setup function is run once before the component is mounted (between beforeCreate and the Created lifecycle). Similar to component initialization, setup needs to return an object or function. The return object is assigned to the component instance’s renderContext and is accessible in the component’s template scope, similar to the return value of data. The return function is treated as the component’s render. See the document for details.

  3. Reactive is the function of wrapping an object into a reactive object, which is represented by a Proxy.

  4. The counter example above, in the component’s setup function, creates a reactive object state containing an age property. We then create a function increment increment, and finally return the state and increment to the scope, so that the button in the template has access to the increment function bound to the click callback, age. We click on the button, and the number on the button increases.

reference

  • Fast advanced Vue3.0:segmentfault.com/a/119000002…
  • Vue Function – RFC:zhuanlan.zhihu.com/p/68477600 -based API

I believe that you have a preliminary understanding of Vue-Next (VUE 3.0), and have successfully run the new code.

The next chapter, VUe-Next (VUE 3.0), continues with the vue-Next functional API.