Summary of new features of Vue3.x and comparison with vue2.x

1. The difference between Vue3.x and Vue2.x

1. The difference between OptionsApi and CompositionApi

Note: You can still use vue2's optional Api writing method in Vue3.x, but I recommend you choose the latest compositional Api writing method

OptionsApi - Vue2.x - Option Api
1. The degree of freedom is limited, and the code must be written in accordance with the regulations, such as props, methods, data, computed, watch, each performing its own duties, and no crossing the boundary is allowed.
2. The context must use this
3. Life The cycle contains beforeCreated() and Created()

CompositionApi - Vue3.x - Composition Api
1. Break up the code and allow free writing in the setup() function, which further reduces the sense of code division
2. Without this, use the context parameter in the setup() function uniformly, by The original this.getData => context.getData
3. The life cycle is replaced by the setup() entry
4. The purpose of Tree-Shaking is to introduce whatever is used, and only the APIs used are packaged in the end

Example:
content context
insert image description here

2. Changes in the life cycle

On the whole, there is not much change. Setup is used to replace the previous beforeCreate and created. The names of other life cycles have changed, and the functions have not changed.
insert image description here

3. The template template supports multiple root tags

  • Adjust from the original single root tag to support multiple root tags, reduce useless code, and increase code freedom!
  • The reason why multiple root tags are supported is because the bottom layer is changed to a Fragment component for wrapping
//Vue2.x写法
<template>
	<div class="name">
		<p></p>
		<p></p>
	</div>
</template>
//Vue3.x
<template>
	<div class="name"></div>
	<div class="name2"></div>
	<div class="name3"></div>
</template>

4.Route gets the page instance and routing information

Vue2.x

  • Get the router instance through this
export default{
    
    
  mounted() {
    
    
    this.getRouter();
  },
  methods: {
    
    
    getRouter() {
    
    
      console.log(this.$route);
      console.log(this.$router);
    },
  },
}

Vue3.x

  • The first is to get the current component instance by using the getCurrentInstance method

import {
    
     getCurrentInstance } from "vue";
export default {
    
    
  setup(props, context) {
    
    
    const {
    
     ctx } = getCurrentInstance();
    console.log(ctx.$router.currentRoute.value);
  },
};
  • The second is through userRoute and userRouter
import {
    
     useRoute, useRouter } from "vue-router";
export default {
    
    
  setup(props, context) {
    
    
    const currRoute = useRoute();
    const currRouter = useRouter();

    console.log(currRoute);
    console.log(currRouter);
  },
};

5. Vuex state management

  • The api has not changed significantly,
  • The way of creating an instance has changed, Vue2.x is new Store, Vue3.x is createStore
//Vue2.x 中创建 store 实例
export default new Vuex.Store({
    
    
   // ... 
})

//Vue3.x
import Vuex from 'vuex'

export default Vuex.createStore({
    
    
  state: {
    
    
    count: 0
  },
  mutations: {
    
    
    ADD (state) {
    
    
      state.count++
    }
  },
  actions: {
    
    
    add ({
     
      commit }) {
    
    
      commit('ADD')
    }
  },
  modules: {
    
    
  }
})

Used in Vue3.x components - two ways

  • the first way
<template>
  <div class="home">
    <p>{
    
    {
    
    count}}</p>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import {
    
     computed } from 'vue'
import {
    
     useStore } from 'vuex'
export default {
    
    
  setup () {
    
    
    const store = useStore()
    const count = computed(() => store.state.count)

    const add = () => {
    
    
      store.dispatch('add')
    }
    
    return {
    
    
      count,
      add
    }
  }
}
</script>
  • The second way: get the store in the current component context
import {
    
    getCurrentInstance} from 'vue'
// ...
const store = getCurrentInstance().ctx.$store

6. Responsive object functions ref and reactive

export default{
    
    
	setup(){
    
    
		const count=ref(0);
		const state=reactive({
    
    
			count:0
		})
	}
}

ref

  • ref is more inclined to define a single variable, while reactive is more inclined to define an object.
  • ref modifies data in the form of count.value=xxx, while reactive only needs state.count=xxx to use
  • ref is equivalent to internally encapsulated reactive
  • ref is regarded as a simple two-way binding variable toRef is to convert non-responsive objects into responsive
  • The template can directly use { {count}} when taking the value

reactive

  • Various methods such as computed properties can be used inside reactive. It just binds the data in two directions.
  • It is best to use toRefs to convert the returned data after reactive
  • When mixed with ref, you can use isRef to judge the type

7. The difference between monitor attribute watch and watchEffect

  • watch needs to specify the attributes (parameters) to monitor, and watchEffect is added in vue3.x, which does not need to specify the attributes (parameters) to monitor, and automatically collects responsive attributes
  • Watch can get the new value and old value (value before update), but watchEffect cannot get it
  • watch specifies dependencies at the beginning, it will not be executed during initialization, and will only be executed when dependencies change,
    while watchEffect will be executed once during initialization to collect dependencies, and watchEffect will be executed again when dependencies change
  • Neither watch nor watchEffect can listen to properties that are not two-way bound
  • watch can directly monitor the objects bound by ref and reactive, but watchEffect cannot (the value of ref should be .value, and the value of reactive should be specific to internal attributes), and it will only be executed for the first time

Summary: By comparing the differences between the two properties, use it reasonably according to specific needs
1. If you need to execute when the component is initialized, use watchEffect
2. If you need to get the new value and the old value, use watch

insert image description here

insert image description here

8. Calculated attribute computed

  • The first type does not allow modification of the value, and a warning will be prompted: Computed properties are not allowed to be modified
  • The second allows modification of the value
    insert image description here

9. Changes in the use of pillar props

  • Used in Vue2.x
exprot default {
    
    
    props: {
    
    
        title: String
    },
    mounted() {
    
    
        console.log(this.title);
    }
}
  • Used in Vue3.x
//通过setup中的内置参数进行调用,舍弃了之前的this调用方式
exprot default {
    
    
    props: {
    
    
        title: String
    },
    //props 组件传入的属性
    setup(props,context) {
    
    
        console.log(props.title) // 响应式
    }
}

10. Mix in Mixins Variations

  • The mixin pattern in Vue2.x looks safe on the surface. But it shares code by merging objects, which invisibly increases the vulnerability of the code, the source of the code is unclear, the conflict of method attributes, etc., and the ability to reason about functions is covered up, so it becomes an anti-pattern.
// vue页面中引入,该方法会将Mixins中的所有方法和属性一并引入
import mixin from 'mixin.js'
export default{
    
    
	data(){
    
    },
	mixins: [mixin]
}
  • The smartest part of the Composition API in Vue3.x is that it allows Vue to share code relying on the safeguards built into native JavaScript, such as passing variables to functions and the module system, and only use the parts that need to be called !
// vue页面中引入
import mixin from 'mixin.js'
//第一种写法 - 利用ES6解构写法,只引用需要的部分
export default{
    
    
	setup(){
    
    
		const {
    
     count, plusOne, hello } = mixin()
		hello()
		console.log(count.value, plusOne.value)
	}
}

// 第二种写法 - 调用组件中的局部变量
export default {
    
    
  setup () {
    
    
    // 某个局部值的合成函数需要用到
    const myLocalVal = ref(0);
    // 它必须作为参数显式地传递
    const {
    
     ... } = mixin(myLocalVal);
  }
}

11. Custom Directives

  • Excerpted from the official document custom directive
  • As the name suggests, custom commands are self-created commands such as v-html, v-bind, v-on, etc. for easy calling
    insert image description here

12. Teleport

  • Official documentation explains Teleport
  • Break away from the original DOM structure, move the DOM elements in the template to other positions, completely controlled by the internal Vue components
  • Solve the level problem of css between components without dealing with z-index problem
  • Solve the positioning problem of Modal, not affected by the parent element
  • Scenarios: Feedback, Notification, Toast, Modal
    Friendly Link: Introduction to Vue3 Teleport, please read it, this is really easy to use

13. Parent-child component passing value

  • When returning data to the parent component, if you use a custom name, such as backData, you need to define it in emits , otherwise an emits option warning will be reported in the console
<template></template>
export default{
    
    
	emits:['backData'],
	setup(props,{
     
     emit}){
    
    
		function back(){
    
    
			emit('backData');
		}
	}
}

2. Small knowledge

1. Does all Vue3-based coding use TypeScript coding?

1. TypeScript is not suitable for business projects with frequent business changes, because speed is the most important thing for this type of requirement.
2. For tools/infrastructure projects, it is best to use TypeScript.

2. When to use defineComponent

Choose the appropriate module according to the language used to write the code

  1. If you use TypeScript, you must use defineComponent when exporting. These two are paired. In order to check the type correctly, as shown in Figure 1
  2. If it is JavaScript coding, this function is not needed, as shown in Figure 2
    insert image description hereinsert image description here

3. The difference between script and script setup

  • After adding the wording after setup, export properties or methods through export
<template>
  <button @click="inc">{
    
    {
    
     count }}</button>
</template>

<script setup>
  import {
    
     ref } from 'vue'

  const count = ref(0)
  const inc = () => count.value++
</script>
  • If you don’t write after setup, you need to return the attribute or method, similar to the return in data() in vue2.x
import {
    
     ref } from 'vue'

export default {
    
    
  setup() {
    
    
    const count = ref(0)
    const inc = () => count.value++

    return {
    
    
      count,
      inc,
    }
  },
}

4. Responsive difference between Object.defineProperty (Vue2) and Proxy (Vue3)

Vue2.x Object.defineProperty

  • Only the getter and setter operations of object properties can be hijacked. When the data changes, it is necessary to traverse all the properties of the object, such as data, props, etc., which consumes a lot
  • Does not support Set/Map, class, array and other types
  • Unable to detect new addition or deletion of attributes, not responsive, need to manually call this.$set to update
  • Object.defineProperty cannot monitor the change of the array subscript, which leads to directly setting the value of the array through the subscript of the array. It cannot respond in real time, and cannot monitor methods such as push. These methods are rewritten in vue to increase the setter
const data= {
    
    
    name: 'xiaoming',
    sex: '男'
}
// 遍历对象,对其属性值进行劫持
Object.keys(data).forEach(key => {
    
    
  let val = data[key]
  Object.defineProperty(data, key, {
    
    
    enumerable: true, // 该属性可被枚举
    configurable: true, // 该属性可以被删除以及属性描述符可以被改变
    get () {
    
    
      console.log(`属性值${
      
      data}当前值为${
      
      val}`)
      return val
    },
    set (newValue) {
    
    
      console.log(`监听到属性值${
      
      data}${
      
      val}变为${
      
      newValue}`)
      val = newValue
    }
  })
});
 
data.name // 属性值name当前值为zhangsan
data.name = 'lisi' // 监听到属性值name由zhangsan变为lisi
data.age // 属性值age当前值为18
data.age = 25 // 监听到属性值age由18变为25

Vue3.x Proxy(ES6)

  • can hijack the entire object
  • The new property of the object can be responded in real time, and the change of the array subscript can be detected
  • Because Proxy is a new attribute of ES6, some browsers do not support it yet, and it is only compatible to IE11
let obj = {
    
    
  a: 1,
  b: 2,
}
 
const p = new Proxy(obj, {
    
    
  get(target, key, value) {
    
    
    if (key === 'c') {
    
    
      return '我是自定义的一个结果';
    } else {
    
    
      return target[key];
    }
  },
 
  set(target, key, value) {
    
    
    if (value === 4) {
    
    
      target[key] = '我是自定义的一个结果';
    } else {
    
    
      target[key] = value;
    }
  }
})
 
console.log(obj.a) // 1
console.log(obj.c) // undefined
console.log(p.a) // 1
console.log(p.c) // 我是自定义的一个结果
 
obj.name = '李白';
console.log(obj.name); // 李白
obj.age = 4;
console.log(obj.age); // 4
 
p.name = '李白';
console.log(p.name); // 李白
p.age = 4;
console.log(p.age); // 我是自定义的一个结果

5. env environment variable configuration

  • Create new .env.development and .env.production in the root directory of the project
  • Custom environment variables must start with VITE_APP
  • Add the corresponding suffix to package.json
  • Call import.meta.env.VITE_APP_BASE_API in the page;
    insert image description here
    insert image description here
console.log(import.meta.env);

6. Initialize data data

Vue2.x

Object.assign(this.$data, this.$options.data());

Vue3.x

 const initState = () => {
    
    
      return {
    
    
        a: 1
      }
    }
 const state = reactive(initState())
    
 const resetState = () => {
    
    
      Object.assign(state, initState())
    }

further reading

If you have already understood the new features of Vue3.x, I recommend you to read the following articles, so that you can quickly get started with Vue3 projects

Guess you like

Origin blog.csdn.net/r657225738/article/details/115551368