在体验Vue3之前,我们先来了解一下Vu3到底有哪些亮点之处。
创新互联成立于2013年,是专业互联网技术服务公司,拥有项目网站建设、网站制作网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元高港做网站,已为上家服务,为高港各地企业和个人服务,联系电话:18980820575
总共有6大特点:
1.理解:vue3.0的组合api舞台是setup
2.setup所有的数据方法等都配置在setup中
3.setup有两种返回值:
4.注意:
5.setup不能是一个async函数,因为返回值不再是return的对象,而是promise,模板看不到return对象中的属性(后期也可以使用suspense和异步组件的配合得到promise)
作用:用于定义一个响应式数据
语法:const name = ref(initValue)
注意:
reactive就是用于将对象数据转为响应式,与vue2的observable类似,而ref用于获得单独或为基础数据类型转为响应式。
为什么在vue3中会有两个将数据转为响应式数据的api,我们来进行详细说明:
简而言之,reactive可以将对象数据转为响应式,可以将对象中的每个元素都转为ref响应式数据;而ref不仅可以将对象数据转为响应式,还可以处理基础数据类型(string、boolean等)。
之所以会有此差异,那时因为vue3中的响应式是基于proxy实现的,而对于proxy的target必须是引用数据类型,即存放在堆内存中通过指针进行引用的对象。为什么是代理的引用数据类型,那是因为简单数据类型每次赋值都是全新的数据,根本无法进行代理,因此难以实现简单数据类型的响应式。
如果我们想要获取简单数据类型的响应式,应该如何做呢?
vue3中也考虑到这点,可以通过ref进行简单数据类型的响应式处理。ref通过创建内部状态,将值挂到value上,因此ref生成的对象要通过.value获取使用。而重写get/set获得的监听,同时对对象的处理也依赖了reactive的实现。
正是如此,ref既可以处理简单数据类型,又可以将引用数据类型进行响应式处理。在实践中,我们应该避免将reactive当作vue2的data在顶部将所有变量进行声明,而是应该结合具体的应用和逻辑进行就近声明。
- class RefImpl
{ - private _value: T
- public readonly __v_isRef = true
- constructor(private _rawValue: T, public readonly _shallow = false) {
- this._value = _shallow ? _rawValue : convert(_rawValue)
- }
- get value() {
- track(toRaw(this), TrackOpTypes.GET, 'value')
- return this._value
- }
- set value(newVal) {
- if (hasChanged(toRaw(newVal), this._rawValue)) {
- this._rawValue = newVal
- this._value = this._shallow ? newVal : convert(newVal)
- trigger(toRaw(this), TriggerOpTypes.SET, 'value', newVal)
- }
- }
- }
- ...
- const convert =
(val: T): T => - isObject(val) ? reactive(val) : val
- ...
vue2的响应式原理:
- Object.defineProperty(data,"count",{
- get(){},
- set(){}
- })
存在问题:
vue3的响应式原理
定义数据
原理
使用
与vue2中的computed配置功能一致
写法:
- import {computed} from "vue";
- setup(){
- const sum = computed(()=>{
- return num1 + num2;
- })
- }
- import {computed,reactive} from "vue"
- setup(){
- const person = reactive({
- firstName:"wen",
- lastName:"bo"
- })
- //简写
- let fullName = computed(()=>{
- return person.firstName + "-" + person.lastName;
- });
- //完整
- let fullName = computed(()=>{
- get(){
- return person.firstName + "-" + person.lastName;
- },
- set(value){
- const newArr = value.split("-");
- person.firstName = nameArr[0];
- person.lastName = nameArr[1];
- }
- })
- }
与vue2中的watch配置功能一致
注意:
- let person = reactive({
- name:"wenbo",
- age:18,
- job:{
- job1:{
- salary:20
- }
- }
- })
- // 情况一:监视ref定义的响应式数据
- watch(sum,(newValue,oldValue)=>{
- console.log("sum变了",newValue,oldValue);
- },{immediate:true})
- // 情况二:监视多个ref定义的响应式数据
- watch([sum,msg],(newValue,oldValue)=>{
- console.log("sum或msg变了",newValue,oldValue);
- })
- /*情况三:监视reactive定义的响应式数据
- 若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue
- 若watch监视的是reactive定义的响应式数据,则强制开启了深度监视
- 此时的deep不生效
- */
- watch(person,(newValue,oldValue)=>{
- console.log("perosn变了",newValue,oldValue);
- },{immediate:true,deep:false})
- //情况四:监视reactive所定义的一个响应式数据中的某个属性
- watch(()=>person.age,(newValue,oldValue)=>{
- console.log("person的age变化了",newValue,oldValue)
- })
- //情况五:监视reactive所定义的一个响应式数据中的某些属性
- watch([()=>person.name,()=>person.age],(newValue,oldValue)=>{
- console.log("person的name或age变化了",newValue,oldValue)
- })
- //特殊情况-监听的对象的属性还是个对象,此时deep生效,可以进行深度监听
- watch(()=>person.job,(newValue,oldValue)=>{
- console.log("person的job变化了",newValue,oldValue)
- },{deep:true})
注意:
watch监听reactive定义的对象有五种情况
watch监听ref定义的响应式数据有两种情况:
watch的套路:既要指明监视的属性,又要指明监视的回调
watchEffect的套路:不用指明监视的哪个属性,监视的回调中用到哪个属性,就监视哪个属性
watchEffect有点类似computed:
- let person = reactive({
- name:"wenbo",
- age:18,
- job:{
- job1:{
- salary:20
- }
- }
- })
- // warchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调
- watchEffect(()=>{
- const x = person.name
- const y = person.job.job1.salary
- console.log("watchEffect触发了")
- })
pageX:{{point.pageX}},pageY:{{point.pageY}}hooks文件 usePoint.js
- import {reactive} from "vue"
- const handleClickPoint = ()=>{
- //实现鼠标“打点”相关数据
- let point = reactive({
- pageX:0,
- pagey:0
- })
- //实现鼠标“打点”相关方法
- const handlePoint = (event)=>{
- point.pageX = event.pageX;
- point.pageY = event.pageY;
- console.log(event.pageX,event.pageY)
- }
- //实现鼠标打点的相关周期函数
- onMounted(()=>{
- window.addEventListener("click",handlePoint)
- })
- onBeforeUnmounted(()=>{
- window.removeEventListener("click",handlePoint)
- })
- }
十、toRef函数
- 经过ref、reactive处理的对象不能直接使用解构进行处理,否则就会失去响应式特性
- 作用:创建一个ref对象,其value值指向另一个对象中的某个属性
- 语法:const name = toRef(person,"name")
- 应用:要将响应式对象中的某个属性单独提供给外部使用时
- 扩展:toRefs与toRef功能一致,但是可以批量创建多个ref对象,语法:toRefs(person)
十一、VUE3生命周期
其它组合式api
1. shallowReactive与shallowRef
shallowReactive:只处理对象最外层属性的响应式(浅响应式)
shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理
使用时机:
- 如果有一个对象数据,结构比较深,但变化时只是外层属性变化==》shallowReactive
- 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生成新的对象来替换==》shallowRef
2. readonly与shallowReadonly
- readonly:让一个响应式数据变为只读数据(深只读)
- shallowReadonly:让一个响应式数据变为只读(浅只读)
- 应用场景:不希望数据被修改时
3. toRaw与markRaw
toRaw
- 作用:将一个由reactive生成的响应式对象转为普通对象
- 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面的更新
markRaw
- 有些值不应该被设置为响应式的,例如:复杂的第三方库
- 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能
- 作用:标记一个对象,使其永远不会称为响应式对象
- 应用场景:
4. customRef
作用:创建一个自定义ref,并对其依赖项跟踪和更新触发进行显式控制
示例:
当前的值:{{str}}
5. provide与inject
- 作用:实现祖孙组件间的通信
- 应用场景:父组件有一个provide选项提供数据,子组件有一个inject来获取使用数据
6. 响应式数据的判断
- isRef:检查一个值是否为ref对象
- isReactive:检查一个值是否为reactive创建的响应式代理
- isReadonly:检查一个对象是否是由readonly创建的只读代理
- isProxy:检查一个对象是否是由reactive或readonly创建的代理
vue3中使用hook注意点
hook中存在异步问题
其实在使用中可以发现,其实hook本质上就是进行抽取的函数,灵活性比较高,但是在涉及到异步逻辑时考虑不周全就会导致很多问题。hook是可以覆盖异步情况的,但是必HTML须在setup当中执行时返回有效对象不能被阻塞。
通常异步具有两种风格:
外部没有其它依赖,只是交付渲染的响应变量。对于此种情况,可以通过声明、对外暴露响应变量,在hook中使用异步修改的方式。
外部具有依赖,需要在使用侧进行加工。对于此种情形,可以通过对外暴露Promise的方式,使得外部获取到同步操作的能力。
this的问题
由于setup处于生命周期的beforeCreate和created阶段之间,因此不能获取到this。当然我们可以通过setup的第二个参数context获取到类似与this的部分能力,但是对于想操作路由、vuex等能力则受到了限制,为此最新的router@4、vuex@4都提供了组合式的api。
由于vue2底层限制使得无法使用这些hook,为此可以通过引用实例的方式获取一定的操作能力,也可以通过getCurrentInstance获得组件实例上挂载的对象。
虽然组合式api的响应式原理是通过Object.defineProperty改写属性的,与vue的响应式原理相同,但是在具体实现方式上存在差异,因此在setup中与vue原生的响应式并不互通。正因此,导致即使拿到相应的实例也没有办法监听它们的响应式,只能通过在选项配置进行使用。
vue3中常见的组件
1. Fragment组件
在vue2中:组件必须有一个根标签
在vue3中:组件可以没有根标签,内部会将多个标签包裹在Fragment虚拟元素中
好处:减少标签层级,减少内存占用
2. Teleport
Teleport时倚重能够将组件html结构移动到指定位置的技术
语法:
main.vue
modal.vue
this is a modal 3. suspense
等待异步组件时渲染一些额外内容,让应用有更好的用户体验。
使用步骤:
- 异步引入组件
- 使用suspense包裹组件,并配置好default与fallback。
- import {defineAsyncComponent} from "vue"
- const child =defineAsyncComponent(()=>import("./components/child.vue"))
【编辑推荐】
- 鸿蒙官方战略合作共建——HarmonyOS技术社区
- 云中的容器:你有哪些选择?
- 5G消息全力迈入发展期
- 什么是域名劫持?遇到域名劫持要怎么处理
- 自学编程,到底先选什么语言?
- 一文看完网络爬虫发展史
分享标题:一网打尽──Vue3Composition-api新特性
网页URL:http://www.csdahua.cn/qtweb/news28/512828.html网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网