Vue3.0

Vue3.0

Vue3.0

  1. Performance
    Vue 2.x 1.2~2
  2. Tree shaking support
    , Vue2.x
  3. Composition API
    : API( React Hooks)
  4. Better TypeScript support
    Ts
  5. Custom Renderer API
    API
  6. Fragment, Teleport(Protal), Suspense

Vue3.0

diff

https://vue-next-template-explorer.netlify.app/ + Vue2 dom dom + Vue3 (PatchFlag) patch flag flag _toDisplayString PatchFlag
//diff <div> <p> </p> <p>{{msg}}}</p> </div> export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("p", null, " "), _createVNode("p", null, _toDisplayString(_ctx.msg) + "}", 1 /* TEXT */) ])) } // : PatchFlags export const enum PatchFlags { TEXT = 1,// CLASS = 1 << 1, //2 // class STYLE = 1 << 2, //4// style PROPS = 1 << 3, //8// FULL_PROPS = 1 << 4, //16// key key diff HYDRATE_EVENTS = 1 << 5, //32// STABLE_FRAGMENT = 1 << 6, //64// fragment KEYED_FRAGMENT = 1 << 7, //128// key fragment key UNKEYED_FRAGMENT = 1 << 8, //256// key fragment NEED_PATCH = 1 << 9, //512// props DYNAMIC_SLOTS = 1 << 10, //1024// slot HOISTED = -1, // // diff BAIL = -2 }

hoistStatic

+ Vue2 , , + Vue3 , , ,
<div> <p> </p> <p>{{msg}}}</p> </div> // : export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("p", null, " "), _createVNode("p", null, _toDisplayString(_ctx.msg) + "}", 1 /* TEXT */) ])) } // : const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, " ", -1 /* HOISTED */) export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _hoisted_1, _createVNode("p", null, _toDisplayString(_ctx.msg) + "}", 1 /* TEXT */) ])) }

cacheHandlers

+ click
<div> <button @click="onClick"> </button> </div> // : export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("button", { onClick: _ctx.onClick }, " ", 8 /* PROPS */, ["onClick"]) ])) } // : export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("button", { onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick(...args))) }, " ") ])) } // : , . Vue3 diff , , .

ssr

+ buffer dom + _createStaticVNode static node node innerHtml

Vue3.0-

Vue3 3 Vue-CLI Webpack Vite

Vite

Vite
Vue
webpack
ES6
import
webpack

Vite

npm install -g create-vite-app
Vite Vue3
create-vite-app projectName

//vite vue3 main.js vue import { createApp } from 'vue' import App from './App.vue' createApp(App).mount('#app') /* new Vue({ el: '#app', store: store, router: router, render: c => c(App) }) new Vue({ store: store, router: router, render: c => c(App) }).$mount("#app"); */

API

import { ref } from 'vue'; export default { name: 'App', setup(){ //setup API // count , 0 , Vue UI let count = ref(0); // let count = 0; // API , , methods , function myFn() { count.value += 1; //count } // API/, , return {xxx, xxx} return{count, myFn} } }

// Vue2 import {reactive} from 'vue'; export default { name: 'App', setup() { /* let state = reactive({//ref , (/) stus:[ {id:1, name:'zs', age:10}, {id:2, name:'ls', age:20}, ] }); function remStu(index) { state.stus = state.stus.filter((stu, idx) => idx !== index); } */ let { state, remStu } = useRemoveStudent(); return { state1, remStu } } } function useRemoveStudent() { // let state = reactive({ stus:[ {id:1, name:'zs', age:10}, {id:2, name:'ls', age:20}, ] }); function remStu(index) { state.stus = state.stus.filter((stu, idx) => idx !== index); } return { state, remStu }; }

js

Composition API
Option API
Vue2.X

Composition API
( API/API)
Option API


setup

1.setup setup beforeCreate: , data methods Created : , data methods 2.setup - setup , Created , setup , data methods - setup data methods, Vue , setup this undefined - setup
//Composition API Option API data: function(){ return { name: 'lnj', } }, methods:{ myFn1(){ alrt('abc'); }, }, setup() { let age = ref(18); //console.log(this);//undefined return {age} }

reactive

**

reactive
Vue3
Vue2
defineProperty
Vue3
ES6
Proxy
**

**

reactive
** :

reactive
(json/arr)
reactive
( eg Date )

Proxy

let state = reactive(123); let state = reactive({age: 123}); let state = reactive([1, 3, 5]);

ref

ref
reactive
reactive
Vue3
ref

ref :

ref
reactive
ref
ref(xx) -> reactive({value:xx})

let state = reactive({ age: 18 }) // let age = ref(18); // function myFn() { //age = 666; age.value = 666; // <p>{{age}}</p> }

ref :

Vue

ref
value
Vue
.value
JS
ref
value

ref

<div ref="box"> div</div> import {ref, onMounted} from 'vue'; setup() { let box = ref(null); //reactive({value: null}) onMounted(()=>{ console.log('onMounted',box.value); // vue2 mounted, }); console.log(box.value); //null }

ref reactive

  • template
    ref
    Vue
    .value
    template
    reactive
    Vue
    .value
  • Vue
    ref
    .value
    .value
  • Vue
    __v_ref
    ref
    , , true,
    ref
import {reactive, ref, isRef, isReactive} from 'vue'; let age = ref(18); let age = reactive({value: 18}); isRef(age) isReactive(age)

ref reactive

,

shallowRef
/
shallowReactive

shallowRef
( ref)
,
triggerRef
.value

shallowReactive
( reactive)
,

// : Vue3 triggerRef , triggerReactive , reactive , . let state = shallowRef({ a:'a', gf:{ b:'b', } }); state.value = { a:'1', gf:{ b:'2', } } state.value.gf.b = '4'; // triggerRef(state); // // : shallowRef , Vue .value , . console.log(state); //shallowReactive proxy key console.log(state.value); //shallowRef proxy

ref reactive

shallowRef
/
shallowReactive


shallowRef

shallowRef
shallowReactive
shallowRef(10) -> shallowReactive({value: 10})
shallowRef
.value
value


toRow

**

Reactive
**
Ref
**
toRaw
** ( )

**

ref/reactive
** UI UI toRaw UI

import {reactive, toRaw} from 'vue'; let obj = {name:'zs', age:18}; let state = reactive(obj); let obj2 = toRaw(state); //obj !== state, obj === obj2 //state obj , state Proxy , Proxy obj

ref
:
ref(obj) -> reactive({value: obj})
toRaw ref ( ) toRaw , .value

import {ref, toRaw} from 'vue'; let obj = {name:'zs', age:18}; let state = ref(obj); let obj2 = toRaw(state.value);

markRaw

Vue

import {reactive, markRaw} from 'vue'; let obj = {name: 'zs', age: 18}; obj = markRaw(obj); let state = reactive(obj); // obj

toRef

ref

ref
toRef
:

ref - , ( ); toRef - , ( );

ref

let obj = {name:'zs'}; let state = ref(obj.name); // reactive({value: zs}) let state = toRef(obj, 'name'); state.value = 'ls'; //

toRefs

ref
,

toRef
ref

toRef - ref , toRefs - ref ,
let obj = {name:'zs', age:18}; let name = toRef(obj, 'name'); let age = toRef(obj, 'age'); // let state = toRefs(obj); state.name.value = 'ls'; // state.age.value = 666;

customRef

**

ref
,
ref
**

<template> <div> <p>{{age}}</p> </div> </template>
import {ref, customRef} from 'vue'; function myRef(value) { return customRef((track, trigger)=>{ return { get(){ // get track(); // Vue return value; }, set(newValue){ // set value = newValue; trigger(); // Vue } } }); } //let age = ref(18);//reactive({value: 18}) let age = myRef(18); age.value += 1;

**

customRef
** setup()

import {ref, customRef} from 'vue'; function myRef(value) { return customRef((track, trigger) => { fetch(value) // es6 fetch json .then((res)=>{ return res.json(); }) .then((data)=>{ console.log(data); value = data; trigger(); }) .catch((err)=>{ console.log(err); }) return { get(){ track(); // Vue // : get // -> get -> // -> -> get return value; }, set(newValue){ value = newValue; trigger(); // Vue } } }); } //setup() let state = myRef('../public/data.json');

readonly & shallowReadonly

**

readonly
shallowReadonly
**

import {readonly, isReadonly, shallowReadonly} from 'vue' let state = readonly({name:'zs', attr:{age:18, height: 1.88}}); state.name = 'ls'; // let state = shallowReadonly({name:'lnj', attr:{age:18, height: 1.88}}); // na me,attr state.name = 'ls'; // state.attr.age = 666; // console.log(isReadonly(state)); //true const value = {name:'zs', age:123}; value.name = 'ls'; //

**

const
readonly
** :

  • const
    ,
  • readonly
    ,

Vue3

Vue2.x
**
defineProperty
Vue3.x
Proxy
**

let obj = {name:'zs', age:18}; let state = new Proxy(obj, { get(obj, key){ console.log(obj, key); //{ name: 'zs', age: 18 } name return obj[key]; }, set(obj, key, value){ console.log(obj, key, value); //{ name: 'zs', age: 18 } name ls obj[key] = value; console.log(' UI '); } }); //console.log(state.name);//lnj state.name = 'ls'; console.log(state); //{ name: 'ls', age: 18 }

Proxy

set Proxy proxy set

let arr = [1, 3, 5]; //[1, 3, 5, 7] let state = new Proxy(arr, { get(obj, key){ console.log(obj, key); return obj[key]; }, set(obj, key, value){ //[ 1, 3, 5 ] 3 7 //[ 1, 3, 5, 7 ] length 4 console.log(obj, key, value); //[ 1, 3, 5 ] 3 7 key 3, 3 obj[key] = value; console.log(' UI '); return true; // true proxy push(7) set length [ 1, 3, 5, 7 ] length 4 } }); //console.log(state[1]);//[ 1, 3, 5 ] 1 state.push(7);

shallowRef/shallowReactive

function shallowRef(val) { return shallowReactive({value:val}); // value } function shallowReactive(obj) { return new Proxy(obj, { get(obj, key){ return obj[key]; }, set(obj, key, val){ obj[key] = val; console.log(' UI '); return true; } }) } let obj = { a:'a', gf:{b:'b'} }; /* let state = shallowReactive(obj); state.a = '1';// UI state.gf.b = '2';// */ let state = shallowRef(obj); //state.value.a = '1';// shallowRef value //state.value.gf.b = '2'; state.value = obj = { a:'a', gf:{b:'b'} }; //state.value.a = '1'; // UI //state.value.gf.b = '2';//

ref/reactive

function reactive(obj) { if(typeof obj === 'object') { if(obj instanceof Array) { // // Proxy obj.forEach((item, index) => { if(typeof item === 'object') { obj[index] = reactive(item) } }) } else { // // Proxy for(let key in obj) { let item = obj[key] if(typeof item === 'object') { obj[key] = reactive(item) } } } } else { console.log(`${obj} is not object`) } return new Proxy(obj, { get(obj, key){ return obj[key]; }, set(obj, key, val){ obj[key] = val; console.log(obj, key , val) console.log(' UI '); return true; } }) } //ref function ref(val) { return shallowReactive({value:val}); } let obj = { a:'a', gf:{b:'b'} }; let state = reactive(obj) state.gf.b = '4'; // UI let arr = [{id: 1, name: 'zs'}, {id: 2, name: 'ls'}] let state2 = reactive(arr) state2[0].name = 'ww' // UI

shallowReadonly/readonly

function shallowReadonly(obj) { //readonly obj readOnly return new Proxy(obj, { get(obj, key){ return obj[key]; }, set(obj, key, val){ console.warn(`${obj[key]} `) } }) } let obj = { a:'a', gf:{b:'b'}}; let state = shallowReadonly(obj) state.a = '1'; //a state.gf.b = '2'; //
function readonly(obj) { if(typeof obj === 'object') { if(obj instanceof Array) { // // Proxy obj.forEach((item, index) => { if(typeof item === 'object') { obj[index] = readonly(item) } }) } else { // // Proxy for(let key in obj) { let item = obj[key] if(typeof item === 'object') { obj[key] = readonly(item) } } } } return new Proxy(obj, { get(obj, key){ return obj[key]; }, set(obj, key, val){ console.warn(`${obj[key]} `) } }) } let obj = { a:'a', gf:{b:'b'}}; let state = readonly(obj) state.a = '1'; //a state.gf.b = '2'; //