Comparison of vue3.0 and vue2.0

Foreword:

            Organize vue3.0 once

table of Contents:

1. Highlights of vue3.0

1. Performance is 1.2~2 times faster than vue2.x

2. Support on-demand compilation, on-demand import, smaller volume than vue2.x

3. Support composite API, similar to React Hooks

4. Better support for ts, because he was written by ts

5. The API for custom rendering is exposed

6. Provided more advanced components

2. How does vue3.0 become faster

1. diff method optimization

2. Static promotion

3. Event listener cache

4.ssr rendering

Three. Three ways to create vue3.0

1. CLI-view

2.Webpack

3. Quick

1) Install Vite

2) Use Vite to create a Vue3.0 project

4. What is Vite? If you want to use Vite here, you can use this to create a project, and the others can directly execute the upgrade command

1. Install vite

2. Use vite to create a vue3.0 project

3. Install and run the project

Five. Combination API

1.ref()

2.reactive() function

3. Mixed use of composition API and Option API

4. Execution timing and points of attention of the setup function

5. Recursive monitoring

6.toRaw() The original data is modified, but the ui will not be updated

7.markRaw() confirms the original data and will never be tracked

8. toRef(), toRef and ref, toRef and toRefs

9.customRef() custom ref


1. Highlights of vue3.0

1. Performance is 1.2~2 times faster than vue2.x

①diff方法优化
②静态提升
③事件侦听器缓存
④ssr渲染

2. Support on-demand compilation, on-demand import, smaller volume than vue2.x

3. Support composite API, similar to React Hooks

4. Better support for ts, because he was written by ts

5. The API for custom rendering is exposed

6. Provided more advanced components

2. How does vue3.0 become faster

1. diff method optimization

  • The virtual dom in vue2.0 is for full comparison
  • Vue3.0 adds a new static flag (PatchFlag), which is that when comparing virtual nodes last time, only nodes with patch flags are compared. And the specific content of the current node to be compared can be known through the information of the flag.
  • Insert picture description here
    Verification: Whether to add
    the URL of the static mark vue3.0 conversion code: https://https://vue-next-template-explorer.netlify.app/
    Insert picture description here
    static mark enumeration class:
    Insert picture description here

2. Static promotion

  • Regardless of whether the element participates in the update, vue2.0 will be recreated every time and then rendered
  • For elements that do not participate in the update, vue3.0 will do static promotion, which will only be newly created once, and can be reused directly during rendering.
  •  

Verification:
By default, the createNode node will be recreated every time, here we choose hoisStatic.
You will find that these nodes are extracted from render and become global variables. You can reuse it every time you render later
Insert picture description here

3. Event listener cache

  • By default, onClick will be regarded as dynamic binding, so it will track its changes every time. But because the function bound to the event is the same function (the same method), there is no tracking change, just cache it and reuse it.
    Verification:
    [Note] You may not understand the converted code, but it does not matter. Because you only need to observe whether there are static marks, because in the diff algorithm of Vue3, only those with static marks will be compared and tracked.
//事件监听缓存
<button @click="onClick">按钮</button>
//开启事件监听缓存之前(把静态提升关闭了也是这样)
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("button", { onClick: _ctx.onClick }, "按钮", 8 /* PROPS */, ["onClick"])
  ]))
}
//开启事件监听缓存之后(把options选择为cacheHandlers)
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)))
    }, "按钮")
  ]))
}

4.ssr rendering

  • When there is a large amount of static content, these content will be pushed into a buffer as pure strings. Even if there is dynamic binding, it will be embedded through template interpolation, which will be much faster than rendering through virtual dom.
  • When the static content reaches a certain level, the _createStaticVNode method will be used to generate a static node on the client side. These static nodes will be directly innerHtml without creating an object, and then rendering according to the object.

Three. Three ways to create vue3.0

1. CLI-view

  • git clone https://github.com/vue.js/vue-next-webpack-preview.git ProjectName
  • cd ProjectName
  • npm install
  • npm run dev

2.Webpack

  • npm install -g @vue/cli
  • vue create ProjectName
  • cd ProjectName
  • vue add vue-next
  • npm run serve

3. Quick

1) Install Vite

npm install -g create-vite-app

2) Use Vite to create a Vue3.0 project

create-vite-app projectName

[Note] I reported an error when using this command. Of course, not everyone encountered this situation. If you don't report an error, you don't need to solve it.
At that time, I checked a lot of information. Some people said that the nodejs version is too low and needs to be upgraded. At first, I upgraded to no effect.
The solution: Configuration nodejs environment variables
① in c \ Program File \ nodejs file folder creation node_cache and node_global two folders
Insert picture description here
② two after you've created an empty folder, open the cmd command window, type

npm config set prefix “C:\Program Files\nodejs\node_global”
npm config set cache “C:\Program Files\nodejs\node_cache”

③Next, set the environment variables, close the cmd window, "My Computer"-right click-"Properties"-"Advanced System Settings"-"Advanced"-"Environment Variables"
④ Enter the environment variable dialog box, under [System Variables] Create a new [NODE_PATH], enter [C:\Program Files\nodejs\node_global\node_modules], modify the [Path] under [User Variables] to [C:\Program Files\nodejs\node_global]
Insert picture description here
Finally, close the black window and restart Next, try the create-vite-app programName command again to see if an error is reported.

3) Install dependent running project

cd projectName
npm install
npm run dev

4. What is Vite? If you want to use Vite here, you can use this to create a project, and the others can directly execute the upgrade command

  • Vite is a tool developed by the author of Vue to replace webpack
  • The implementation principle is to use the feature of es6 import to send requests to load files, intercept these requests, do some pre-compilation, and save webpack's lengthy packaging time

1. Install vite

cnpm install -g create-vite-app

2. Use vite to create a vue3.0 project

create -vite -app projectName

3. Install and run the project

cd projectName
npm install

Five. Combination API

Problems with vue2.x:
Combination API of vue3.x: The
setup function is the entry function of the combination API

1.ref()

1) What is ref?
      Like reactive, ref is also a method used to implement responsive data. Since reactive must pass an object, it will be very troublesome in enterprise development if we only want a variable to be responsive, so vue3 provides us with a ref method to monitor simple values.

2) The essence of ref The essence of
     ref is actually reactive. When we pass a value to the ref function, the bottom layer of the ref function will automatically convert ref to eactive, such as ref(10)—>reactive({value:18}).
Note:
    ① If the data is created by tref, you don't need to use .value to get it when using it in the template, because vue will automatically add .value to us.
    ② However, the ref function used in js must be obtained through value.

3) Ref function and usage
     function: only simple type changes can be monitored.
     Usage: import introduces {ref}, return exposes. The variable to get ref needs .value

<script>
import {ref} from 'vue'
export default {
  name: 'App',
  setup(){
    let count=ref(0);

    function changeBtn(){
      count.value++;
    }
    return {count,changeBtn}
  }
}
</script>

2.reactive() function

1) What is reactive?
      ①Reactive is the method to realize responsive data provided
      in vue3 ; ②In vue2, responsive data is realized through defineProperty, and in vue3, responsive data is realized through es6's Proxy.

2)
      Reactive note: ①The reactive parameter must be an object (obj/json/arr)
      ②If other objects (such as date objects) are passed to reactive, the interface will not be updated if the object is modified by default; if you want to update, you can By reassigning

3) Function and usage
      function: monitor the changes of objects and arrays.
       Usage: import introduces {reactive}, return exposes the method name.

<script>
import {ref} from 'vue'
import {reactive} from 'vue'
export default {
  name: 'App',
  setup(){
    let {state,remStu}=useRemoveStudent()
    return {state,remStu}
  }
}
//整个相关的方法和变量都写在一起了
  function useRemoveStudent(){
    let state=reactive({
      stus:[
        {id:1,name:'张三',age:10},
        {id:2,name:'李四',age:20},
        {id:3,name:'王五',age:30},
      ]
    });
    function remStu(index){
      state.stus=state.stus.filter((stu,idx)=>idx!==index);
    }
    return {state,remStu}
  }

</script>

The idea of ​​composite API: the
entire related methods and variables are written together

demo2: delete and add users

<template>
  <div>
    <form action="">
      <input type="text" v-model="state2.stu.id">
      <input type="text" v-model="state2.stu.name">
      <input type="text" v-model="state2.stu.age">
      <input type="submit" @click="addStu">
    </form>
    <ul>
      <li v-for="(stus,index) in state.stus" :key="stus.id"
      @click="remStu(index)">
        {
   
   {stus.name}}--{
   
   {stus.age}}
      </li>
    </ul>
  </div>
</template>

<script>
import {ref} from 'vue'
import {reactive} from 'vue'
export default {
  name: 'App',
  setup(){
    let {state,remStu}=useRemoveStudent()
    let {state2,addStu}=useAddStudent(state)
    return {state,remStu,state2,addStu}
  }
}
//删除用户
  function useRemoveStudent(){
    let state=reactive({
      stus:[
        {id:1,name:'张三',age:10},
        {id:2,name:'李四',age:20},
        {id:3,name:'王五',age:30},
      ]
    });
    function remStu(index){
      state.stus=state.stus.filter((stu,idx)=>idx!==index);
    }
    return {state,remStu}
  }
//增加用户
function useAddStudent(state){
  let state2=reactive({
    stu:{
      id:'',
      name:'',
      age:''
    }
  });
  function addStu(e){
    e.preventDefault();
    const stu=Object.assign({},state2.stu);
    state.stus.push(stu)
    state2.stu.id=''
    state2.stu.name=''
    state2.stu.age=''
  }
  return {state2,addStu}
}

</script>

[ Note ]
① The difference between ref and reactive :
          If you use ref type data in the template, then vue will automatically add .value for us,
         if you use reactive data in the template, then vue will not automatically help us Add .value.
②How does vue decide whether to add .value automatically?
        Vue will automatically determine whether the data is of ref type before parsing the data,
        if it is, it will automatically add .value, if it is not, it will not automatically add .value.
③How does vue judge whether the current data is of ref type?
        Judged by the __v_ref of the current data. If there is this private attribute and the value is true, then it represents a ref type of data.
④How does the developer judge the current data type?
        isRef and isReactive to determine whether they are ordinary functions and objects, respectively.

3. Mixed use of composition API and Option API

The option API is the previous vue2.x API
composition AP is now the new syntax of vue3.x The
composition API and Option API can be mixed.

What is the essence of composition API?
It can be translated as: composite API (or injection API).
Its essence is to inject the data exposed in the composition API into the Option API at runtime. For example, if a common variable age is exposed, the age will be injected. Go to the data() method; a method submit() is exposed, and this method will be injected into the methods.

4. Execution timing and points of attention of the setup function

1) The timing of execution of the
     setup function : The setup function is executed between beforeCreate and created.
     beforeCreate: indicates that the component has just been created, and the data and methods of the component have not yet been initialized;
     created: indicates that the component has just been created, and the data methods of the component have been initialized.

2) Setup notes:
     ① Since the created life cycle method has not been executed when the setup function is executed, data and methods cannot be used in the setup function.
     ②Because we cannot use data and methods in the setup function, Vue directly changes the this value in the setup function to Undefined in order to avoid our wrong use.
     ③The setup function can only be synchronous, not asynchronous.

5. Recursive monitoring

1) Recursive monitoring
By default, whether through ref or reactive is recursive monitoring

<template>
  <div>
    <p>{
   
   {state.a}}</p>
    <p>{
   
   {state.gf.b}}</p>
    <p>{
   
   {state.gf.f.c}}</p>
    <p>{
   
   {state.gf.f.s.d}}</p>
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {ref} from 'vue'
import {reactive} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=reactive({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.a='1';
      state.gf.b='2';
      state.gf.f.c='3';
      state.gf.f.s.d='4';
      console.log(state)
      console.log(state.gf)
      console.log(state.gf.f.s)
    }
    return {state,myFn}
  }
}


</script>

2) Problems with recursive monitoring
If the amount of data is large, it consumes performance. Because he wraps each layer into a proxy object.
Insert picture description here

3) Non-recursive monitoring
shadowRef / shallowReactive
non-recursive monitoring means that it can only monitor the first layer, not other layers.
[Use scenario] We only use it when the amount of data that needs to be monitored is relatively large.
①shallowReactive

<script>
import {shallowReactive} from 'vue'
import {shallowRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=shallowReactive({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.a='1';
      state.gf.b='2';
      state.gf.f.c='3';
      state.gf.f.s.d='4'
      console.log(state)
      console.log(state.gf)
      console.log(state.gf.f.s)
    }
    return {state,myFn}
  }
}


</script>

You will find that only the first layer is packaged as a proxy

Insert picture description here

If shallowRef creates data by shallowRef, then Vue monitors the changes in .value, not the first-level changes.
Essence: ref(10)->reactive({value:10}), because the bottom layer is essentially the first layer.

<script>
import {shallowReactive} from 'vue'
import {shallowRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=shallowRef({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.value.a='1';
      state.value.gf.b='2';
      state.value.gf.f.c='3';
      state.value.gf.f.s.d='4'
      console.log(state)
      console.log(state.value)
      console.log(state.value.gf)
      console.log(state.value.gf.f.s)
    }
    return {state,myFn}
  }
}

Insert picture description here
So the letters above did not become numbers. If you want to turn it into a number, you need to change the state directly

<script>
import {shallowReactive} from 'vue'
import {shallowRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=shallowRef({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.value={
          a:'4',
          gf:{
            b:'5',
            f:{
              c:'6',
              s:{
                d:'7'
              }
            }
          }
      }
      state.value.a='1';
      state.value.gf.b='2';
      state.value.gf.f.c='3';
      state.value.gf.f.s.d='4'
      console.log(state)
      console.log(state.value)
      console.log(state.value.gf)
      console.log(state.value.gf.f.s)
    }
    return {state,myFn}
  }
}


</script>

Insert picture description here

③shallowRef only wants to modify the data of the fourth layer. If the fourth layer is changed, it will automatically modify the UI interface. Use with triggerRef.
[Note] Vue3 only provides the triggerRef method, not the TriggerReactive method. So if it is reactive type data, it cannot actively trigger interface updates.

<script>
import {shallowReactive} from 'vue'
import {shallowRef,triggerRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=shallowRef({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.value.gf.f.s.d='8';
      triggerRef(state)
      console.log(state)
      console.log(state.value)
      console.log(state.value.gf)
      console.log(state.value.gf.f.s)
    }
    return {state,myFn}
  }
}


</script>

Insert picture description here

6.toRaw() The original data is modified, but the ui will not be updated

The characteristics of ref/reactive data type:
every modification will be tracked and the ui interface updated. But this is actually very performance-consuming. If you do not need to update the ui interface, you can get his original data through the toRaw method. At this time, when the original data is modified, it will not be tracked and the ui interface will not be updated.

<template>
  <div>
    {
   
   {state}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {reactive,toRaw} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    let state=reactive(obj)//注意:如果这里是ref的话,下面toRaw(state.value)
    let obj2=toRaw(state)
    function myFn(){
      // state.name="Angle";//会更新ui界面
      obj2.name="Angle";//数据虽然被改变了,不会更新ui界面。这样会减少性能的消耗
      console.log(obj2)
    }
    return {state,myFn}
  }
}


</script>

Insert picture description here

7.markRaw() confirms the original data and will never be tracked

<template>
  <div>
    {
   
   {state}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {reactive,markRaw} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    obj=markRaw(obj)//永远不会被追踪
    let state=reactive(obj)
    function myFn(){
      state.name="Angle";
      console.log(obj)
    }
    return {state,myFn}
  }
}


</script>

Insert picture description here

8. toRef(), toRef and ref, toRef and toRefs

The application scenario of toRef:
If you want to associate the responsive data with the previous data, and you do not want to update the ui after updating the responsive data.

The difference between ref and toRef:
ref: equivalent to copying, modifying the responsive data will not affect the previous data; toRef: equivalent to quoting, modifying the responsive data will affect the previous data;
ref: the interface is updated when the data changes; toRef: The data changes, the interface is not updated;

ref->A fairly new copy, without changing the original data. But the data in the ref package has changed, and the change will update the page.

<template>
  <div>
    {
   
   {state}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {reactive,ref} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    let state=ref(obj.name)
    function myFn(){
      state.value="Angle";
      console.log(obj)//没有改变obj
      console.log(state)//state是新的复制出来的一份
    }
    return {state,myFn}
  }
}


</script>

Insert picture description here
->toRef reference, the original data is changed, but the interface is not updated:

<template>
  <div>
    {
   
   {state}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {reactive,toRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    let state=toRef(obj,'name')
    function myFn(){
      state.value="Angle";
      console.log(obj)//因为引用,所以改变了
      console.log(state)//改变了,但界面没更新
    }
    return {state,myFn}
  }
}


</script>

Insert picture description here
toRefs is a shorthand for multiple uses of toRef:

<script>
import {reactive,toRef,toRefs} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    let name=toRef(obj,'name');
    let age=toRef(obj,'age');
    // let state=toRef(obj);//简写
    function myFn(){
      name.value="Angle";
      age.value=18;
      // state.name.value='Angle';
      // state.age.value=18;
      console.log(obj)//因为引用,所以改变了
      console.log(state)//改变了,但界面没更新
    }
    return {state,myFn}
  }
}


</script>

9.customRef() custom ref

Returns a ref object, which can be tracked and triggered accordingly.
Track() is triggered when get, telling vue that this data needs to track changes;
when set, trigger() is triggered. Tell vue to trigger an interface update.

<template>
  <div>
    {
   
   {age}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {ref,customRef} from 'vue'
function myRef(value){
  return customRef((track,trigger)=>{
    return{
      get(){
        track();//告诉vue这个数据是需要追踪变化的
        console.log('get',value)
        return value;
      },
      set(newValue){
        console.log('set',newValue)
        value=newValue;
        trigger();//告诉vue触发界面更新
      }
    }
  })
}
export default {
  name: 'App',
  setup(){
   let age=myRef(18);
   function myFn(){
     age.value+=1;
   }
    return {age,myFn}
  }
}


</script>

Usage scenario: Asynchronous requests are convenient for customization, which does not look like asynchronous.

<template>
  <div>
    <ul>
      <li v-for="item in state" :key="item.id">{
   
   {item.name}}</li>
    </ul>
  </div>
</template>

<script>
import {ref,customRef} from 'vue'
function myRef(value){
  return customRef((track,trigger)=>{
      //异步
      fetch(value)
      .then((res)=>{
        return res.json()
      })
      .then((data)=>{
        console.log(data);
        value=data;
        trigger();
      })
      .then((err)=>{
        console.log(err)
      })
    return{
      get(){//不能在get中发送异步请求,否则会死循环
        track();//告诉vue这个数据是需要追踪变化的
        console.log('get',value)
        return value;
      },
      set(newValue){
        console.log('set',newValue)
        value=newValue;
        trigger();//告诉vue触发界面更新
      }
    }
  })
}
export default {
  name: 'App',
  setup(){
   let state=myRef('./assets/data.json')
    return {state}
  }
}


</script>

Guess you like

Origin blog.csdn.net/weixin_44727080/article/details/112977564