From Vue2 to Vue3 [4] - Composition API (Chapter 4)

Series Article Directory

content Link
From Vue2 to Vue3 [zero] Introduction to Vue3
From Vue2 to Vue3 [1] Composition API (Chapter 1)
From Vue2 to Vue3 [2] Composition API (Chapter 2)
From Vue2 to Vue3 [3] Composition API (Chapter 3)
From Vue2 to Vue3 [4] Composition API (Chapter 4)


foreword

With the release of Vue 3, we ushered in a powerful and exciting composition API , which brings more flexibility and maintainability to developers . Vue 3's composition API not only changed the way we write Vue components, but also introduced some new components and some small but practical changes . In this article, we will explore in depth the customRef, provide and inject in the Vue 3 combined API and the judgment of responsive data , let us start this exciting learning journey together!

1. customRef

  • customRef:

    • Create a custom ref with explicit control over its dependency tracking and update triggering.
    • customRef is suitable for scenarios that require custom read and write logic .
    • Provides more flexibility to customize the behavior of reading and writing according to specific needs .
    • It can be seamlessly integrated with the responsive system to maintain a consistent Vue development experience.

ref is actually very similar to customRef, both of which can create responsive data, let’s talk about their similarities and differences

  • Same point:
  1. Responsive: Both customRef and ref can create responsive data .
  2. Access value: Both customRef and ref can access the internal value through the .value attribute . (you need to add .value when operating the value)
  • the difference:
  1. Creation method: customRef needs to pass in a function, and define custom read and write logic in the function ; while ref only needs to pass in the initial value .

  2. Read and write logic: customRef allows you to define your own read and write logic, which can achieve more flexible responsive behavior ; while ref will directly access the internal value.

  3. Dependency Tracking: customRef allows you to manually track dependencies in read and write logic through track and trigger functions ; ref will automatically track read and write dependencies.

<template>
	<input type="text" v-model="keyword">
	<h3>{
    
    {
    
    keyword}}</h3>
</template>

<script>
	import {
    
    customRef} from 'vue'
	export default {
    
    
		name:'Demo',
		setup(){
    
    
			//自定义一个myRef
			function myRef(value,delay){
    
    
				let timer
				//通过customRef去实现自定义
				return customRef((track,trigger)=>{
    
    
					return{
    
    
						get(){
    
    
							track() //告诉Vue这个value值是需要被“追踪”的
							return value
						},
						set(newValue){
    
    
							clearTimeout(timer) // 当再次输入时清空上次的定时器 重新开启一个新的定时器
							timer = setTimeout(()=>{
    
    
								value = newValue  // 直到在delay这段时间不再输入时 才会更新模板上的值
								trigger() 通知Vue去重新解析模板
							},delay)
						}
					}
				})
			}
			let keyword = myRef('hello',500) //使用程序员自定义的ref
			return {
    
    
				keyword
			}
		}
	}
</script>

The official case given by this official: When the user enters the input, the delayed update of the h3 tag below ( 本质上就是一个防抖)
anti-shake means that if the event is triggered again within a certain period of time, the timing will be restarted, and the event will not be executed until it is not triggered again within this period; while throttling means that the event can only be triggered once within a certain period of time . In terms of implementation, technologies such as timers or time stamps can be used to implement. Among them, anti-shake is suitable for scenarios such as search boxes that require the input of complete keywords to produce final results ; throttling is more suitable for scenarios that require frequent triggers but each execution event takes a long time.

Please add a picture description

myref is a custom function, so it needs to have a return value. The returned value is the responsive data customized by customRef. There are
getters and setters inside customRef. When parsing the template, you need to read the value (getter), and when you enter the input, you need to reset the value (setter)


insert image description here
When modifying the value when initially reading the value
insert image description here
In summary , both customRef and ref are functions provided by Vue 3 for creating responsive data. Their main differences lie in the creation method , reading and writing logic , and dependency tracking . You can choose which function to use to create responsive data according to your needs.
The use of customRef in real scenarios should be combined with whether the processing of the component library is supported. It cannot be well applied to the component library, because the component library has its own data hijacking
( 响应式实现原理数据劫持这块,在讲完vue3的基本使用后,会出一篇文章详细讲解,欢迎订阅本系列,长期更新!)

Two, provide and inject

  • provide and inject
    • Provide and inject are a pair of special combinations used to realize the transfer of data from parent components to descendant components . They help us share data across levels in the component tree without passing props down the hierarchy.

    • The provide function receives two parameters: provide( name, value ),

      • name: Defines the name of the data provided to descendants.
      • value : Provides the value of the data.
    • inject(name,default)

      • name: Receive the attribute name provided by provide.

      • default: Set the default value, which is an optional parameter.
        ( 当父亲没有provide值时,子组件注入使用的就是默认值,默认值也没有的话就是undefined)

The parent component uses an provideoption to provide data, and the descendant components use a injectto receive and use the data

parent component code

<template>
  <div class="app">
    <h3>我是App组件(祖),{
   
   { name }}--{
   
   { price }}</h3>
    <Child />
  </div>
</template>

<script>
import {
      
       reactive, toRefs, provide } from "vue";
import Child from "./components/Child.vue";
export default {
      
      
  name: "App",
  components: {
      
       Child },
  setup() {
      
      
    let car = reactive({
      
       name: "奔驰", price: "40W" });
    provide("car", car); //给自己的后代组件传递数据
    setTimeout(() => {
      
      
      // 过一秒钟修改父亲的car 看下子组件数据是否改变 若改变 则说明传递给子孙组件的数据也是响应式的
      car.name = '宝马'
    }, 1000);
    return {
      
       ...toRefs(car) };
  },
};
</script>

<style>
.app {
      
      
  background-color: gray;
  padding: 10px;
}
</style>

subcomponent code

<template>
	<div class="child">
		<h3>我是Child组件(子),{
   
   { name }}--{
   
   { price }}</h3>
		<Son/>
	</div>
</template>

<script>
	import {
      
      inject, toRefs} from 'vue'
	import Son from './Son.vue'
	export default {
      
      
		name:'chIld',
		components:{
      
      Son},
		setup(){
      
      
			let car = inject('car')
			return {
      
      
				...toRefs(car)
			}
		} 
	}
</script>

<style>
	.child{
      
      
		background-color: skyblue;
		padding: 10px;
	}
</style>

grandson component code

<template>
	<div class="son">
		<h3>我是Son组件(孙),{
   
   {car.name}}--{
   
   {car.price}}</h3>
	</div>
</template>

<script>
	import {
      
      inject} from 'vue'
	export default {
      
      
		name:'sOn',
		setup(){
      
      
			let car = inject('car')
			return {
      
      car}
		}
	}
</script>

<style>
	.son{
      
      
		background-color: orange;
		padding: 10px;
	}
</style>

Effect (the parent component transmits responsive data to the descendant components, and after the father modifies the value, the data of the descendant components will also change)
Please add a picture description

The Vue framework adopts 单向数据流the data management mode ===> descendant components are not allowed to modify the value passed down from the parent component, which will cause unclear data flow and bold style

  • This data flow design has the following advantages:

    • The flow of data is clear and controllable: data is passed from parent components to child components, forming a clear data flow path, so that data changes can be traced and controlled.
    • Component independence: Subcomponents only need to care about their own data and logic, and do not need to care about the specific implementation details of the parent component, which improves the independence and reusability of components.
    • Data predictability: Since data can only flow from parent components to child components, data changes can only be triggered by parent components, reducing the complexity and unpredictability of data.

Therefore, although provide and inject are used to transfer data between the parent component and the descendant components, the data cannot be modified in the descendant components. In order to avoid this problem, when the parent component passes values, it should use readonly to restrict the descendant components from modifying data. Upgraded version of the parent component to pass
values

    provide("car", readonly(car)); //给自己的后代组件传递只读数据

Consequences of modifying values ​​in subcomponents: Errors are reported, and values ​​cannot be modified, nice!

			setTimeout(() => {
				car.name = '五菱宏光'
			}, 2000);

insert image description here

3. Judgment of responsive data

  • isRef: checks if a value is an refobject
  • isReactive: checks if an object was reactivecreated by a reactive proxy
  • isReadonly: checks if an object was readonlycreated by a read-only proxy
  • isProxy: Checks if an object is a proxy created by the reactiveor methodreadonly
<template>
	<h3>我是App组件</h3>
</template>

<script>
	import {
      
      ref, reactive,toRefs,readonly,isRef,isReactive,isReadonly,isProxy } from 'vue'
	export default {
      
      
		name:'App',
		setup(){
      
      
			let car = reactive({
      
      name:'奔驰',price:'40W'})
			let sum = ref(0)
			let car2 = readonly(car)

			console.log(isRef(sum)) //true
			console.log(isReactive(car)) //true
			console.log(isReadonly(car2)) //true
			console.log(isProxy(car)) //true
			console.log(isProxy(sum)) //false

			
			return {
      
      ...toRefs(car)}
		}
	}
</script>

<style>
	.app{
      
      
		background-color: gray;
		padding: 10px;
	}
</style>

insert image description here

4. Composition API and Options API

  • Options API
    In the Options API, various options (data, methods, computed, watch) of components are defined and organized through individual configuration items. Such a design can lead to scattered code , especially in large components, it is difficult to track and manage the association between various options.
    Please add a picture description
  • Composition API
    In the composition API, various functional options can be combined according to their logical relevance
    Please add a picture description

In the composition API, you can use the setup() function to organize and define the logic of the components. Various functional functions (such as reactive, ref, computed, etc.) can be used in the setup() function to declare reactive data, computed properties, event handling functions, etc., without dispersing them in different options. This makes the logic code more centralized and easier to maintain.

In addition, because the combined API combines data and logic, the code of the component is more modular and reusable (hooks). Different logic can build different components by combining different functional functions, which improves the maintainability and readability of the code.

In summary, as can be seen in the figure, the use of combined APIs can combine related logic together, simplifying the code structure, and providing better readability and maintainability. Compared with the Options API, the combined API is more flexible and powerful, especially suitable for complex components and large projects.

Summarize

At this point in this series, after explaining the combined API, we will bring you new components and small changes.

Guess you like

Origin blog.csdn.net/m0_57524265/article/details/131863726