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
- Runtime-core Specifies the runtime core
-
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