Welcome to join us to learn and make progress together.

I will post the latest news and excellent articles as soon as possible.

Video on b standing video www.bilibili.com/video/BV1fa…

About release Time

You can look at the official schedule. Official schedule

Vue3 is currently in Beta, and the rest of it deals with stability issues. That said, there won’t be many improvements to the main Api. You said from the live broadcast that although there are many ideas, big changes will appear in 3.1 at the earliest. So the current version should be very different from the official version. It looks like there’s a good chance that Q2 will be released.

Mind maps

>>>>>>>️ Brain map link <<<<<<<

Vue3 Family bucket address

Project Status
vue-router Alpha [Proposed RFCs] [GitHub] [npm]
vuex Alpha, with same API [GitHub] [npm]
vue-class-component Alpha [Github] [npm]
vue-cli Experimental support via vue-cli-plugin-vue-next
eslint-plugin-vue Alpha [Github] [npm]
vue-test-utils Alpha [Github] [npm]
vue-devtools WIP
jsx WIP

Gracefully manage source version

In order to be able to reference the vue3 source code in the test project and to upgrade gracefully in the next version update. I decided to use Git’s submodule feature for management

Git submodule introduce blog.csdn.net/guotianqing…

Initialize the submodule

git submodule add https://github.com/vuejs/vue-next source/vue-next
Copy the code

The submodule contents are recorded in a.gitModules file

# Update module
git submodule init
# Update module
git submodule update --init --recursive
Copy the code

Compile source code

Install dependencies

## Modify the image
yarn config set registry https://registry.npm.taobao.org --global
yarn config set disturl https://npm.taobao.org/dist --global

# # remove pupteer
Ignore downloading Chromium
yarn --ignore-scripts
Copy the code

Package compiled

yarn dev
Copy the code

HelloWorld

Classic API

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src=".. /.. /source/vue-next/packages/vue/dist/vue.global.js"></script>
</head>

<body>
    <div id='app'></div>
    <script>
        const App = {
            template: `  `.data() {
                return {
                    message: 'Hello Vue 3!! '}},methods: {
                click() {
                    console.log('click .... '.this.message)
                    this.message = this.message.split(' ').reverse().join(' ')}}}let vm = Vue.createApp(App).mount('#app')
        // console.log(vm)
    </script>
</body>

</html>
Copy the code

Composite API

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src=".. /.. /source/vue-next/packages/vue/dist/vue.global.js"></script>
</head>

<body>
    <div id="app"></div>
    <script>
        const { createApp, reactive,watchEffect } = Vue
        const App = {
            template: `  `.setup() {
                const state = reactive({
                    message:'Hello Vue 3!! '
                })
                watchEffect(() = > {
                    console.log('state change ', state.message)
                })
                function click() {
                    state.message = state.message.split(' ').reverse().join(' ')}return {
                    state,
                    click
                }
            }
        }
        createApp(App).mount('#app')
    </script>
</body>

</html>

Copy the code

Browser breakpoint debugging

Install dependencies to compile the source code

Local files can be opened directly through the browser

You can try it with a click and then if you want to debug the source code you’ll find that the code is packaged and you can’t directly debug the source code with breakpoints

Add the SourceMap file

Add Sourcemap to the packaged code in order to see the source code in the browser and enable breakpoint debugging

 Set the environment variable Windows
 set SOURCE_MAP=true && yarn dev
 Set environment variable MAC/Linux
 export SOURCE_MAP=true && yarn dev
Copy the code

CompositionApi introduction

Alpha source code. In this article, we take a look at one of the most important RFC motion apis in version 3.0.

concept

CompositionAPI can be translated into composite API if only literally. It used to be called Vue function-based API, but I think it’s more descriptive now. Essentially, the CompositionAPI is designed to make it easier to implement combinations of logic.

Review of history

Vue2 if you want to achieve logical compliance in components, such as all button components to achieve shake, there are about three ways to choose:

  • Mixins
  • Higher- Order Components (aka HOCs)
  • Renderless Components (Components that encapsulate logic based on Scoped slots/Scoped slots

But all three are not very ideal, there are major problems

  • The template data source is not clear, such as mixin, it is difficult to tell where an attribute comes from just by looking at the template.
  • Namespace conflict
  • Performance issues. For example, HOC requires additional component logic nesting, resulting in unnecessary performance overhead.

But what I’m more concerned about is that I have to introduce other concepts to deal with the primitive programming behavior of combining logic. This, of course, is why many architects who switch from Java prefer React. Vue is the language that goes in laughing and comes out crying. Getting started seems easy enough to just look at HelloWorld and work, but as soon as you run into problems you need to introduce a new concept. It’s not as clean and natural as the React function or component.

motivation

Let’s look at it first

const App = {
            template: `  `.data() {
                return {
                    message: 'Hello Vue 3!! '}},methods: {
                click() {
                    console.log('click .... '.this.message)
                    this.message = this.message.split(' ').reverse().join(' ')}}}let vm = Vue.createApp().mount(App, '#app')
Copy the code

Options API source location

The classic Vue API can be summarized as the Options API, which can be understood as an API for declaring logic in a configuration based manner. What that means is basically defined. Think about vuE2’s HelloWorld as if it were just a few simple definitions to achieve functionality. I think that’s why vue is so popular and it’s really simple to describe general logic. Of course, this also has a lot to do with yu Dashen from designer origin. Don’t let CSS and HTML languages be completely definable code.

However, this expression can be problematic if the business logic is complex. Because once the logic is complicated and you can’t write it as a lump, you have to think about how to organize it, you have to think about extracting the common parts of the logic and thinking about reuse, otherwise it becomes very difficult to maintain. What are the three ways of reuse that have been mentioned in the previous article? On the one hand, it requires new concepts and on the other hand, the programming experience is really poor and there are performance issues.

The CompositionAPI was inspired (admittedly) by The React Hooks. Good things need to be learned from this and don’t look down on the chain. Using the function composition API, the association API can be extracted into a composition function that encapsulates the associated logic and returns the state that needs to be exposed to the component as a responsive data source.

In actual combat

Ok on the code, the first piece of logic is especially large logic mouse position listening logic

    // A classic example of mouse position listening logic
    function useMouse() {
            const state = reactive({
                x: 0.y: 0
            })
            const update = e= > {
                state.x = e.pageX
                state.y = e.pageY
            }
            onMounted(() = > {
                window.addEventListener('mousemove', update)
            })
            onUnmounted(() = > {
                window.removeEventListener('mousemove', update)
            })
            return toRefs(state)
        }

Copy the code

We also want to put together another piece of logic like the refresh time logic

function useOtherLogic() {
            const state = reactive({
                time: ' '
            })
            onMounted(() = > {
                setInterval(() = > {
                    state.time = new Date()},1000)})return toRefs(state)
        }
Copy the code

In real life we can assume that these two logics are likely to be reused by many components, and think about how irrelevant you would be if you used mixin and hoc. But using the motion API, we just need to combine it and expose like this

       const MyComponent = {
            template: `<div>x:{{ x }} y:{{ y }} z:{{ time }} </div>`.setup() {
                const {
                    x,
                    y
                } = useMouse()
                // Use with other functions
                const {
                    time
                } = useOtherLogic()

                return {
                    x,
                    y,
                    time
                }
            }
        }
        createApp().mount(MyComponent, '#app')
Copy the code

It’s… it’s… it’s… it’s… it’s… Welcome to star for complete examples

Full API Introduction

What are the basic apis for Vue3?

const {
            createApp,
            reactive, // Create a responsive data object
            ref, // Create a responsive data object
            toRefs, // Convert the reactive data object to a single reactive object
            isRef, // Check whether a value is a reference type
            computed, // Create the computed properties
            watch, // Create a watch listener
            // Lifecycle hooks
            onMounted,
            onUpdated,
            onUnmounted,
        } = Vue
Copy the code

Setup uses the entry to the Composition API

The setup function is executed after beforeCreate and before created

setup(props,context){
    console.log('setup.... '.)console.log('props',props) // Component parameters
    console.log('context',context) // Context object
} 

Copy the code

Ok, you can actually match your original React Vue2 code.

reactive

The reactive() function takes a normal object and returns a reactive data object

    const state = reactive({
        count: 0.plusOne: computed(() = > state.count + 1)})Copy the code

Ref and isRef

  • Ref creates a responsive data object for the given value (specifically, the basic data type ini or string)
  • IsRef is just trying to figure out if it’s a reactive data object generated by ref

First of all, there is an important concept called a Value wrapper. If you’re talking about a Java wrapper, you’ll remember the Java concept of a Wrapclass. We know that only value without reference to basic data types, it creates a problem to return a basic data type such as a string is unable to trace his status, so we need to speak basic data type packaging, it’s a bit like the useRef ReactHooks, but data source object itself is the response of the Vue packing type. All right, let’s look at an example to understand

    // Define to create responsive data
    const time = ref(new Date())
    // Set the timer to test the data response
    setInterval(() = > time.value = new Date(), 1000)

    // Check whether a value is of response type
    console.log('time is ref:', isRef(time))
    console.log('time', time)
    console.log('time.value', time.value)
    
    // Let's take a look at the template and show it like this
    template: ` 
      
Date is {{ time }}
`
Copy the code

toRefs

  • ToRefs expands objects created by reactive as base types
    // If toRefs are not used
    const state = reactive({
        count: 0.plusOne: computed(() = > state.count + 1)})return {
        state
    }
    // Template rendering should be written like this
    template: ` 
      
count is {{ state.count }}
plusOne is {{ state.plusOne }}
`
// Let's see if we use toRefs again const state = reactive({ count: 0.plusOne: computed(() = > state.count + 1)})return { ...toRefs(state) } // Template rendering should be written like this template: `
count is {{ count }}
plusOne is {{ plusOne }}
`
Copy the code

Watch defines the listener

There’s nothing new about this, okay

   watch(() = > state.count * 2.val= > {
        console.log(`count * 2 is ${val}`)})Copy the code

Effect side effect function

Reactive object modifications trigger this function

    // Side effect function
    effect(() = > {
        console.log(The 'value has been modified.. ',state.count)
    })
Copy the code

Computed attribute

const state = reactive({
    count: 0.plusOne: computed(() = > state.count + 1)})Copy the code

A. life cycle Hooks

Vue3 Vue3
beforeCreate The setup (alternative)
created The setup (alternative)
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestroy onBeforeUnmount
destroyed onUnmounted
errorCaptured onErrorCaptured

Complete code implementation

Get an in-depth look at the source code through Jest

Now it’s time to move on to principle source. There’s a small problem we need to take care of first. Just figuring out how to get the Vue3 unit test running. After all, reading code without running it is soulless. Skew the Chinese fans are not just watching.

The Vue3 code is tested against Jest. Let’s take a quick look at what is Jest

Jest profile

Jest is a dedicated Javascript unit testing tool for Facebook. It is suitable for JS, NodeJS, zero configuration, built-in code coverage, powerful Mocks and other features.

In short, at present, Jest is a set of relatively system testing tools. Why is that? For example, if you compare Mocha to the previous testing framework, which was just a testing framework, if you need assertions you need a specialized assertion library like Assert, shoud, Expect, etc., and if you need mocks you need their own libraries to support them. But Jest can be done almost all at once.

Directory file Name Convention

Jest test code and logic code is convention over configuration, which is generally accepted in the programming world today.

The test code for Jest is based on the following convention

  • The test file name should be a spec result
  • The test file suffix is JS, JSX, TS, and TSX
  • The test file needs to be in the tests/unit/ directory or /tests/ directory

As long as the test file meets these three requirements, it will be automatically executed when using jEST.

This is similar to Maven’s convention for test code and logic code except that the test directory is changed to __tests__

Let’s take a look at the directory structure of the Vue3 source code in detail

So, it’s a little bit easier to put the logical code and the test code together. Let’s look at another package, reactive

Run full tests

Jest is configured in the package.json file

npm run test
Copy the code

coverage

We added a parameter to get the coverage out

npx jest --coverage 
Copy the code

In fact, there was a mistake in running coverage so let’s just leave that alone and let’s just parse this report for a second how do you look at it, if you’ve studied software engineering you know that in general the theory of coverage is covered, right

  • Statement coverage
  • The node coverage
  • Path coverage
  • Conditional combination coverage

But in general, different frameworks understand different things and in the case of Jest, it’s sort of broken down like this

  • % STMTS is statement coverage: Is every statement executed?
  • %Branch Branch coverage: Is every if block executed?
  • %Funcs function coverage: Is every function called?
  • %Lines Line coverage: Is every line executed?

Run a separate test

For example, let’s look at vue’s index test

There are two ways to test separately

// Install globally
npm i jest -g
jest index

// Or even easier
npx jest index
Copy the code

index.spec.ts

import { createApp } from '.. /src'

it('should support on-the-fly template compilation'.() = > {
  const container = document.createElement('div')
  const App = {
    template: `{{ count }}`.data() {
      return {
        count: 0
      }
    }
  }
  createApp().mount(App, container)
  / / assertions
  expect(container.innerHTML).toBe(` 0 `)})Copy the code

It says that in order to make sure that the template compilation works, this is a simple data binding and the last assertion is to see if the count is zero. So in this case, except for the assertion part, it actually works by copying directly into that HTML file that WE saw in the first lecture.

Reactive unit tests

See that the corresponding test code for each package is placed in the __tests__ file

    npx jest reactive --coverage
Copy the code

After that we can start to enter the source code

The code structure

The source code is located in the package file. In fact, the source code is mainly divided into two parts, the compiler and the runtime environment.

  • The compiler

    • Compiler-core Specifies the core compilation logic

      • Basic type resolution
      • AST
    • Compiler-dom is the compiler logic for the browser

      • v-html
      • v-text
      • v-model
      • v-clock
  • Runtime environment

    • Runtime-core Specifies the runtime core
      • inject
      • The life cycle
      • watch
      • directive
      • component
    • Runtime – DOM Runtime logic for browsers
      • class
      • style
    • Running-test Indicates the simulation of the test environment

      It is easier to test logic that is primarily designed to solve unit testing problems out of the browser

  • Reactivity Reactive logic

  • The Template-Explorer template parser can run like this

    yarn dev template-explorer
    Copy the code

    Then open index. HTML

  • Vue Code entry

    Integrate the compiler and runtime

  • Server -renderer

  • Share Common method

Comparison of response modes between Vue2 and Vue3

What is the Vue2 response

First, let’s talk about what a response is. There’s some way that you can get to the point where the data changes and you can freely define the corresponding response and that’s called a response.

The specific need for our ViewModel in MVVM is that the data changes and the view needs to respond. This is the case with the Jest use case

    it('Test whether data changes are responded to'.() = > {
        const data = reactive({
            name: 'abc'.age: {
                n: 5}})Mock a response function
        const fn = jest.fn()
        const result = fn()

        // Set the response function
        effect(fn)

        // Change the data
        data.name = 'efg'

        // Confirm that fn is valid
        expect(fn).toBeCalled()
    })
Copy the code

Let’s say that what we want is data and when data changes we can trigger the FN function which is the corresponding function, which usually triggers the view update or it may not. We have made a Mock function with jest to check if the corresponding function is made.

Finally, the code expect(fn).tobecalled () is effective, which means that the test is passed, which is made accordingly

Vue2 solution

The following shows that vuE2 is implemented by redefining getter and setter methods using object.defineProperty.

let effective
function effect(fun) {
    effective = fun
}

function reactive(data) {
    if (typeofdata ! = ='object' || data === null) {
        return data
    }


    Object.keys(data).forEach(function (key) {
        let value = data[key]
        Object.defineProperty(data, key, {
            emumerable: false.configurable: true.get: () = > {
                return value
            },
            set: newVal= > {
                if(newVal ! == value) { effective() value = newVal } } }) })return data
}

module.exports = {
    effect, reactive
}
Copy the code

Of course, there are two important issues that need to be addressed. The first is that you can only do the shallow response if you do the second layer.

it('Tests whether changes in multiple layers of data are responded to'.() = > {
        const data = reactive({
            age: {
                n: 5}})Mock a response function
        const fn = jest.fn()

        // Set the response function
        effect(fn)

        // Change multiple layers of data
        data.age.n = 1

        // Confirm that fn is valid
        expect(fn).toBeCalled()
    })
Copy the code

For example, in the following use case, the solution is to have recursive calls

And, of course, there’s also a huge performance cost to recursion that you keep in mind.

And then we have the array problem which we can solve by hijacking functions

const oldArrayPrototype = Array.prototype
const proto = Object.create(oldArrayPrototype);

['push'.'pop'.'shift'.'unshift'.'splice'.'sort'.'reverse'].forEach(method= > {
    
    // Function hijacking
    proto[method] = function(){
        effective()
        oldArrayPrototype[method].call(this. arguments) } })// Arrays provide responses through data hijacking
if(Array.isArray(data)){
    data.__proto__ = proto
}

Copy the code

Vue3

The new version of Vue3 uses ES6’s Proxy approach to solve this problem. The two previous problems were much simpler. First of all, Proxy supports arrays so you don’t have to do any special code for arrays. There is no need to use recursion for deep listening. When get is an object, the object can be processed in a reactive manner and returned. If you think about it it’s not at initialization time it’s at setup time and of course it’s a big performance boost.

function reactive(data) {
    if (typeofdata ! = ='object' || data === null) {
        return data
    }
    const observed = new Proxy(data, {
        get(target, key, receiver) {
            // Reflect returns a value with no error
            let result = Reflect.get(target, key, receiver)

            // Multilayer agents
            return typeofresult ! = ='object' ? result : reactive(result) 
        },
        set(target, key, value, receiver) {
            effective()
            // proxy + reflect
            const ret = Reflect.set(target, key, value, receiver)
            return ret
        },

        deleteProperty(target,key){
            const ret = Reflect.deleteProperty(target,key)
            return ret
        }

    })
    return observed
}

Copy the code

Of course, there are pros and cons, such as compatibility issues, currently IE11 does not support Proxy. However, it is not a matter of believing that full support for ES6 is irreversible.

To compare and understand the difference between the responsive implementations of Vue2 and vu3, I have written both implementations together with the JEST test. We can refer to github.com/su37josephx…

// cloneCode YARN NPX jest reactivity-demoCopy the code

Custom renderer

This custom renderer is similar to React’s Render. A variety of renderers can be defined as needed

  • Vue – Native App side
  • There should be many such libraries on the applet side
  • WebGL vugel. Planning. Nl / # applicatio…

Specific content will be updated recently

New tool vite

We know that import is fully available in the browser in ES6 syntax. It can be used to load backend resources but it’s a feature we’ve been ignoring. Maybe webPack is so good. We’ve been ignoring his existence. Vite takes advantage of this feature, but takes it one step further by providing support for vue files. But maybe it’s a little edgy.

  • Simple Http server
  • Without webpack
  • Vue files are rendered directly
  • Hot update