vue3的部分新增API与其他的一些常用到的改变

本文介绍了Vue3的新特性,包括toRef的使用,它允许将响应式对象的属性引用到外部。还讨论了其他组合式API如shallowReactive、readonly、customRef以及provide和inject。文章详细解释了它们的作用和应用场景,并提到了Vue3中组件、全局API和其他变化,如Fragment、Suspense和移除的特性。
摘要由CSDN通过智能技术生成

toRef

作用:创建一个ref对象,其value值指向另一个对象中的某个属性。新的ref 把传来的reactive的源数据地址拿过来 ,指向的地方换成指定的

语法:const name = toRef(person , " name " ) const name = toRef(person.job.j1 , " salary" )

为什么不能用ref:ref的本质是拷贝,与原始数据无关联。toRef的本质是引用,与原始数据有关联。用ref等于生成新数据,那么它改变的时候原始数据是不变的

应用场景:要将响应式对象中的某个属性单独提供给外部使用时,并且还需要响应式。

引出多个:toRefs

​ 与toRef功能一致,但可以批量创建多个ref对象,语法: toRefs(person)。但是这个只能浅拷贝,也就是只能得到对象第一层的属性,如果属性是对象,里面的属性还是要自己去取出来。

  setup() {
​    *let* person = reactive({
​      name: '张三',
​      age: 18,
​      job: {
​        j1: {
​          salary: 18
​        }
​      }
​    })

​    return {
​      person,
​      name: toRef(person, 'name'),
​      age: toRef(person, 'age'),
​      salary: toRef(person.job.j1, 'salary'),

​      //直接拆分多个,这样写必须用到扩展运算符,因为返回值是一个对象,所以要拆分出来
​      //...toRef(person) 
​    }
  }

其他组合式API

shallowReactive 与shallowRef

shallowReactive:只处理对象最外层属性的响应式(浅响应式)。

与reactive的区别就是 reactive会使所有层次的属性都变成响应式,而shallowReactive只有第一层的属性变成响应式

shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理

与ref的区别:如果传入的是一个对象,那么ref就会求助于reactive去处理,而使对象也可以进行响应式。而shallowRef则只处理基本类型,传入对象没有响应式

应用场景:

  • 如果有一个对象数据,结构比较深,但变化的只是外层属性变化===> shallowReactive,
  • 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换(比如置空对象的属性)===>shallowRef。

深层没响应式,但是第一层改变貌似shallowReactive会替换所有数据,出现了第一层改变,然后刷新了深层的数据显示


readonly 与shallowReadonly

readonly:让一个响应式数据变为只读的(深只读),这时候所有数据都不能修改
shallowReadonly:让一个响应式数据变为只读的(浅只读),这时候深层的数据可以被修改

应用场景:不希望数据被修改时。比如别人定义的数据,不希望被修改,引入的时候可以加一个readonly;或者前期需要响应,后期不可修改,就可以使用这个API


toRaw 与markRaw

toRaw:

作用:将一个由reactive生成的响应式对象转为普通对象。
应用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。

markRaw :
作用:标记一个对象,使其永远不会再成为响应式对象。修改对象的值控制台看会改变,但是页面不做响应式
应用场景:

  1. 有些值不应被设置为响应式的,例如复杂的第三方类库等。
  2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
function showRawPerson(){
    const p = toRaw(person)
    p.age++
    console.log(p)
}

function addCar(){
    let car = {name:'奔驰',price:40}
    person.car = markRaw(car)
}

customRef

作用:实现一个自定义的ref,也是可以响应式的,但是可以添加更多功能,比如防抖等

使用:

  1. 引入customRef这个API
  2. 定义一个函数调用这个API,函数的参数是你使用时myRef时候传过来的。一定要把这个API返回return!!!!
  3. 调用customRef,它的参数是一个函数,而且这个函数也必须要有返回值(第二个return)。
  4. customRef的参数函数的参数是track和trigger,他们分别负责追踪变化和通知重新解析模板
  5. 如果需要的是响应式,那么返回值里面就要有get和set,get里面要用track()追踪数据是否发生了变化,而set里面用trigger()通知重新vue解析模板(记得把set得到的新值去重新赋给get里面需要重新读取的变量)
  6. 变化的过程是:修改数据 —— set监测到数据修改,trigger()通知重新解析 —— get里面track()追踪数据的变化,把值重新读取出来
<template>
  <!-- Vue3可以没有根标签 -->
  <input type="text" v-model="keywords" />
  <h3>{{ keywords }}</h3>
</template>

<script>
import { customRef } from 'vue'

export default {
  name: 'App',
  setup() {
​    *let* timer
​    *function* myRef(*value*, *delay*) {
​      return customRef((track, trigger) *=>* {
​        return {

​          get() {
​            track()
​            return *value*
​          },

​          set(*newValue*) {
​            clearTimeout(timer)
​            timer = setTimeout(() *=>* {
​              *value* = *newValue*
​              trigger() //通知vue重新解析模板
​            }, *delay*)
​          }
​        }
​      })
​    }

​    *let* keywords = myRef('hello', 500)
​    //使用程序员自定义的ref
​    return {
​      keywords,
​      myRef
​    }
  }
}
</script>

provide与inject

作用:实现祖孙组件间通信(隔代通信,跨级通信)。子代其实也可以收到,但是一般不用这种方式,父子一般用props。

使用方式:祖组件用provide,子组件用inject。这样得到的数据也是响应式的

祖组件:

import { reactive, toRefs, provide } from 'vue'
import AppSon from './components/Son.vue'

export default {
  name: 'App',
  components: { AppSon },

  setup() {
​    *let* person = reactive({ name: 'zs', age: '18' })
​    provide('people', person)
​    return { ...toRefs(person) }
  }
}

孙组件:

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


响应式数据判断的API
  • isRef:检查一个值是否为一个ref 对象

  • isReactive:检查一个对象是否是由reactive创建的响应式代理

  • isReadonly:检查一个对象是否是由readonly创建的只读代理。被readOnly修饰过的数据还是响应式的,只是不可以修改的。

  • isProxy:检查一个对象是否是由reactive或者readonly方法创建的代理


Composition API 组合式API的优势

  1. vue2中 Options API存在的问题

    使用传统的Options API时,新增或者修改一个需求,就需要分别在data、methods、computed、watch等里面不断地寻找、修改

  2. vue3中 Composition API的优势

    更加优雅的组织我们的代码、函数,让相关功能的代码更加有序的组织在一起。甚至可以把他们都变成一个个hook函数,修改那部分就可以直接去对应的文件里修改。

新的组件
Fragment:
  • vue2中组件必须有一个根标签
  • Vue3中组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中。

好处:减少标签层级,减小内存占用

Teleport

能够将我们的组件传送到指定位置

如下,比如需要弹窗,又不想让弹窗把原本内容撑开,那么就可以把它传到body上。就不会影响其他组件。

<teleport to="body">
    <div v-if="isShow" class="mask">
        <div class="dialog">
            <h3>我是一个弹窗</h3>
            <h4>aa</h4>
            <h4>aaaa</h4>
            <h4>aaaaa</h4>
            <button @click="isShow = false">关闭弹窗</button>
        </div>
    </div>
</teleport>
Suspense

等待异步组件时渲染一些额外内容,让应用有更好的用户体验

Suspense内部本身有两个插槽,一个叫default,一个叫fallback。default里面是要展示的组件,fallback里面是加载中时候显示的内容

使用步骤:

  1. 异步引入组件

    import {defineAsyneComponent} from 'vue '
    const Child = defineAsyncComponent(()=>import ('./ components/Child.vue'))
    
  2. 使用Suspense包裹组件,并配置好default 与fallback

    <template>
        <div class="app">
        <h3>我是App组件</h3>
        <Suspense>
            <template v-slot:default>
                <child/>
            </template>
            <template v-slot:fallback>
                <h3>加载中.....</h3>
            </template>
        </Suspense>
        </div>
    </template>
    

前面说setup不能是一个async函数, 因为返回值不再是retum的对象,而是promise,模板看不return对象中的属性。只有这个时候可以返回一个Promise实例,!!!必须Suspense和异步组件配合使用

async setup(){
	let sum = ref(0)
	let p = new Promise((resolve,reject)=>{
		setTimeout(()=>{
			resolve({sum})
		},3000)
	})
	return await p
}

vue3的其他变化

全局API的转移
  • Vue 2.x有许多全局API和配置。
    例如:注册全局组件、注册全局指令等。

    //注册全局组件
    Vue.component('MyButton', {
    	data: () => ({
    	count: 0
    	}),
    	template: ' <button @click-"count++">Clicked {{count}} times</button>
    })
    //注册全局指令
    Vue.directive('focus', {
    	inserted: el => el.focus()
    }
    
  • Vue3中对这些API做出了调整,将全局的API调整到应用实例app上

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VFR0zNW8-1650098358694)(E:\markdown\前端\csdn\20220416_1.png)]

其他改变
  • data选项应始终被声明为一个函数

  • 过度类名的更改,就是在开始的那个位置上加了一个-from

    • Vue2.x写法

      .v-enter,
      .v-leave-to {
      	opacity: 0;
      }
      .v-leave,
      .v-enter-to {
      	opacity: 1;
      }
      
    • Vue3.x写法

      v-enter-from, 
      .v-leave-to {
      	opacity: e;
      }
      .v-leave-from,
      .v-enter-to {
      	opacity: 1;
      }
      
  • 移除了keyCode作为v-on的修饰符,同时也不支持config.keyCodes了(自定义按键别名,别名的定义也是依赖keyCode的,所以一并移除了)

  • 移除了v-on.native修饰符

    父组件中绑定事件:

    <my- component
    	v-on:close="handleComponentEvent"
    	v-on:click="handleNativeClickEvent"
    />
    

    子组件中声明自定义事件:子组件emits里面接收的就是自定义事件,不接收就默认是原生事件

    <script>
    export default {
    	emits: ['close']
    }
    </script>
    
  • 移除了过滤器 filter

-on的修饰符,同时也不支持config.keyCodes了(自定义按键别名,别名的定义也是依赖keyCode的,所以一并移除了)

  • 移除了v-on.native修饰符

    父组件中绑定事件:

    <my- component
    	v-on:close="handleComponentEvent"
    	v-on:click="handleNativeClickEvent"
    />
    

    子组件中声明自定义事件:子组件emits里面接收的就是自定义事件,不接收就默认是原生事件

    <script>
    export default {
    	emits: ['close']
    }
    </script>
    

vue3的视频看完啦,后面整理一下vue2和vue3的内容,明天开始做项目进行实践了,理论学完了还要有实战经验

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值