ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

vue3的新特性

2022-02-28 23:58:32  阅读:198  来源: 互联网

标签:name reactive 对象 setup 特性 person vue3 ref


vue3的新特性

一、setup

1、是vue3.0的中的一个新增配置项,值为一个函数。
2、setup是所有composition API(组合式api)展示的舞台。
3、setup函数的两种返回值:
若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)
若返回一个渲染函数:则可以自定义渲染内容。(了解) (不常用)
注意点:
1、尽量不要和vue2.x版本混用。

  • vue2.x版本可以访问到setup里的属性。
  • setup访问不到vue2.x版本的属性。
  • 如果有重名,setup优先

2、setup不能是一个async函数,因为返回值不再是对象, 而是promise, 模板看不到return对象中的属性。
3、setup执行顺序在beforeCreat,并且在setup中this为undefined
4、setUp(props, contex)接受两个参数

  • props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性(其实就是vue2.0的props功能)
  • context:上下文对象(其中可以获取到1、attrs组件外部传递过来,但没有在props配置中声明的属性。2、slots:插槽内容3、emit:分发自定义事件的函数,并且以后在setup中不能写this.$emit,要写context.emit)
<template>
  <h2>姓名:{{name}}</h2>
  <h2>年龄:{{age}}</h2>
  <button @click="sayInfo">显示信息</button>
</template>

<script>
export default {
  name: "App",
  setup(){
  	//此时的数据不具有双向绑定的功能
    let name = "小明"
    let age = 18

    // 方法
    function sayInfo(){
      alert(`你好${name},你太厉害了吧`)
    }
    // 想要在模板中使用setup中的方法或者数据,必须return
    return {
      name,age, gender,sayInfo
    }
     // return ()=> h('h1','试试')
  }
};
</script>


二、ref

作用:定义一个响应式数据。
语法:let xxx = ref(xxx)
注意点:

  • ref(),括号中可以填基本数据类型和也可以是对象类型
    • 填基本数据类型会返回一个RefImpl的实例对象,RefImpl类中有getter和setter可以检测到数据的变化。
    • 填对象类型的数据:其实就是使用了Vue3.0中的一个新函数—— reactive函数。
  • js操作值的方法是xxx.value,模板中直接{{xxx}}
  • 使用之前要先引入。
<template>
  <h2>姓名:{{ name }}</h2>
  <h2>年龄:{{ age }}</h2>
  <button @click="changeInfo">修改信息</button>
</template>

<script>
import { ref } from "vue";
export default {
  name: "App",
  setup() {
    // 数据
    let name = ref("小明");
    let age = ref(18);
    // 方法
    function changeInfo() {
      name.value = "小明";
      age.value = 48;
    }
    return {
      name,
      age,
      changeInfo,
    };
  },
};
</script>

三、reactive

作用:定义一个响应式对象。
语法:let xxx = reactive(xxx)
注意点:

  • reactive(),括号要填对象类型
    • 填基本数据类型会返回一个proxy实例对象。
    • 填对象类型的数据:其实就是使用了Vue3.0中的一个新函数—— reactive函数。
  • js操作值的方法是xxx.value,模板中直接{{xxx}}
  • 使用之前要先引入。
  • 上面ref()方法虽然也可以填对象,但是他的本质还是调用了reactive方法,并且js操作时还需要xxx.value,多此一举。而且使用reactive()定义的响应式对象是深层次的,不会出现vue2对象数据层级过深,不改变的情况。
<template>
  <h2>姓名:{{ yk.name }}</h2>
  <h2>年龄:{{ yk.age }}</h2>
  <h2>爱好:{{ yk.hobby }}</h2>
  <h3>测试数据:{{ yk.job.a.b.c }}</h3>
  <button @click="changeInfo">修改信息</button>
</template>

<script>
import { reactive } from "vue";
export default {
  name: "App",
  setup() {
    // 数据
    let yk = reactive({
      age: 18,
      hobby: ["吃饭", "睡觉", "打豆豆"],
      job: {
        a: {
          b: {
            c: 666,
          },
        },
      },
    });

    // 方法
    function changeInfo() {
      yk.age = 48;
      yk.job.a.b.c = 888;
      // 直接通过数组下标修改,可以触发响应式
      yk.hobby[0] = "打豆豆";
    }
    return {
      yk,
      changeInfo,
    };
  },
};
</script>

三、计算属性computed

与vue2.x相比,功能几乎一样,但是写法有些许变动。

<template>
  姓:<input v-model="person.firstName"></input>
 名: <input  v-model="person.lastName"></input>
  姓名:<input  v-model="person.fullName"></input>
</template>

<script>
//先引入
import {computed,reactive } from 'vue'
export default {
  name: "App",
  setup() {
  	let person = reactive({
		firstName :"小",
		lastName:"明",
		fullName:""
	})
    //计算属性 —— 简写
    //let fullName = computed(()=>{
       // return person.firstName + '-' + person.lastName
    //})
    //计算属性 —— 完整
    person.fullName = computed({
        get(){
            return person.firstName + '-' + person.lastName
        },
        set(value){
            const nameArr = value.split('-')
            person.firstName = nameArr[0]
            person.lastName = nameArr[1]
        }
    })
    return {
     person
    };
  },
};
</script>

三、计算属性watch

和计算属性差不多,在vue3中和只是语法上上的改变。
注意点:

  • 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)
  • 监视reactive定义的响应式数据中某个属性时(这个属性需是对象):deep配置有效
//情况一:监视ref定义的响应式数据
watch(sum,(newValue,oldValue)=>{
	console.log('sum变化了',newValue,oldValue)
})
//如果用ref定义了一个对象
watch(person.value,(newValue,oldValue)=>{
	console.log('person变化了',newValue,oldValue)
})
 
//情况二:监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{
	console.log('sum或msg变化了',newValue,oldValue)
}) 
//情况三:监视reactive定义的响应式数据
watch(person,(newValue,oldValue)=>{
	console.log('person变化了',newValue,oldValue)
},{immediate:true,deep:false}) //此处的deep配置不再奏效

//情况四:监视reactive定义的响应式数据中的某个属性
watch(()=>person.job,(newValue,oldValue)=>{
	console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true}) 

//情况五:监视多个reactive定义的响应式数据中的某些属性
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
	console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})

//特殊情况
//person.job中的job也是一个对象
watch(()=>person.job,(newValue,oldValue)=>{
    console.log('person的job变化了',newValue,oldValue)
},{deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效


四、watchEffect函数

watch是:既要指明监视的属性,也要指明监视的回调。
watchEffect是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
这个函数的功能和计算属性差不多,但是

  • 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
  • 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
    const x1 = sum.value
    const x2 = person.age
    console.log('watchEffect配置的回调执行了')
})

五、生命周期钩子

1、vue3.0中可以继续使用vue2.x中的生命周期钩子,但是有两个被更名:

  • beforeDestroy改成beforUnmount
  • destroyed改成 unmounted

2、vue3.0也提供了composition API形式的生命周期钩子,与vue2.x钩子对应关系如下:

  • beforeCreate======>setup()
  • created==========>setup()
  • beforeMount======>onBeforeMount
  • mounted=========>onMounted
  • beforeUpdate=====>onBeforeUpdate
  • updated =========>onUpdated
  • beforeUnmount ===>onBeforeUnmount
  • unmounted ======>onUnmounted

六、自定义hook函数

  • 什么是hook?-------本质是一个函数,把setup中使用的compositionAPI进行了封装。
  • 类似于vue2.x中的mixin。
  • 自定义hook的优势:复用代码,让setup中的逻辑更清晰。
  • emmmm感觉就是模块导入,和vue2.x 的mixin也有些许差别。

创建一个hook文件夹,里面创建文件point.js

import { reactive, onMounted, onBeforeUnmount } from "vue";
export default function() {
    //实现鼠标“打点”相关的数据
    let point = reactive({
        x: 0,
        y: 0,
    });

    //实现鼠标“打点”相关的方法
    function savePoint(event) {
        point.x = event.pageX;
        point.y = event.pageY;
        console.log(event.pageX, event.pageY);
    }

    //实现鼠标“打点”相关的生命周期钩子
    onMounted(() => {
        window.addEventListener("click", savePoint);
    });

    onBeforeUnmount(() => {
        window.removeEventListener("click", savePoint);
    });

    return point;
}

在组件中使用

<template>
<h2>当前点击时鼠标的坐标为:x:{{point.x}},y:{{point.y}}</h2>
</template>

<script>
  import usePoint from '../hook/point.js'
  export default {
    name:'HelloWorld',
    setup(){
      const point = usePoint()
      return {point}
    }
  }
</script>

七、toRef和toRefs

  • 作用:创建一个 ref 对象,其value值指向另一个对象中的某个属性。
  • 语法:const name = toRef(person,‘name’)
  • 应用: 要将响应式对象中的某个属性单独提供给外部使用时。
  • 扩展:toRefs与toRef功能一致,但可以批量创建多个 ref 对象,语法:toRefs(person)
<template>
	<h4>{{person}}</h4>
	<h2>姓名:{{name}}</h2>
	<h2>年龄:{{age}}</h2>
	<h2>薪资:{{job.j1.salary}}K</h2>
	<button @click="name+='~'">修改姓名</button>
	<button @click="age++">增长年龄</button>
	<button @click="job.j1.salary++">涨薪</button>
</template>

<script>
	import {ref,reactive,toRef,toRefs} from 'vue'
	export default {
		name: 'HelloWorld',
		setup(){
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})
			
			// const name1 = person.name
			// console.log('%%%',name1)

			// const name2 = toRef(person,'name')
			// console.log('####',name2)

			const x = toRefs(person)
			console.log('******',x)

			return {
				person,
				// name:toRef(person,'name'),
				// age:toRef(person,'age'),
				// salary:toRef(person.job.j1,'salary'),
				...toRefs(person)
			}
		}
	}
</script>

八、其他新特性

1、shallowReactive 与 shallowRef

  • shallowReactive:只处理对象最外层属性的响应式(浅响应式)。
  • shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理。
  • 什么时候使用?
    1、如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive。
    2、如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 ===> shallowRef。

2、readonly 与 shallowReadonly

  • readonly: 让一个响应式数据变为只读的(深只读)。
  • shallowReadonly:让一个响应式数据变为只读的(浅只读)。
  • 应用场景: 不希望数据被修改时。

3、toRaw 与 markRaw

toRaw
作用:将一个由reactive生成的响应式对象转为普通对象。
使用场景:

  • 用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。

markRaw
作用:标记一个对象,使其永远不会再成为响应式对象。
应用场景:

  • 有些值不应被设置为响应式的,例如复杂的第三方类库等。
  • 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能

4、customRef

作用:创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。

实现防抖效果

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

<script>
import { customRef } from "vue";
export default {
  name: "App",
  setup() {
    //自定义一个ref——名为:myRef
    function myRef(value, delay) {
      let timer;
      return customRef((track, trigger) => {
        return {
          get() {
            console.log(`有人从myRef这个容器中读取数据了,我把${value}给他了`);
            track(); // 通知Vue追踪value的变化(提前和get商量一下,让他认为这个value是有用的)
            return value;
          },
          set(newValue) {
            console.log(`有人把myRef这个容器中数据改为了:${newValue}`);
            clearTimeout(timer);
            timer = setTimeout(() => {
              value = newValue;
              trigger(); // 通知Vue去重新解析模板
            }, delay);
          },
        };
      });
    }

    // let keyWord = ref('hello') //使用Vue提供的ref
    let keyWord = myRef("hello", 500); //使用程序员自定义的ref

    return { keyWord };
  },
};
</script>

5、provide 与 inject

作用:实现祖与后代组件间通信

套路:父组件有一个 provide 选项来提供数据,后代组件有一个 inject 选项来开始使用这些数据

具体写法
祖组件中:

setup(){
	......
    let car = reactive({name:'奔驰',price:'40万'})
    provide('car',car) // 给自己的后代组件传递数据
    ......
}

后代组件中:

setup(props,context){
	......
    const car = inject('car') // 拿到祖先的数据
    return {car}
	......
}

6、响应式数据的判断

isRef: 检查一个值是否为一个 ref 对象。
isReactive: 检查一个对象是否是由 reactive 创建的响应式代理。
isReadonly: 检查一个对象是否是由 readonly 创建的只读代理。
isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理。

九、新的组件

1、Fragment

在Vue2中: 组件必须有一个根标签
在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中
好处: 减少标签层级, 减小内存占用

2、Teleport

Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。

3、Suspense

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

使用步骤:

异步引入组件

import {defineAsyncComponent} from 'vue'
const Child = defineAsyncComponent(()=>import('./components/Child.vue'))

使用Suspense包裹组件,并配置好default与 fallback

<template>
	<div class="app">
		<h3>我是App组件</h3>
		<Suspense>
		//default:就是组件要显示的内容
			<template v-slot:default>
				<Child/>
			</template>
			//fallback:就是组件没加载完全的“备胎”
			<template v-slot:fallback>
				<h3>加载中.....</h3>
			</template>
		</Suspense>
	</div>
</template>

十、其他变化

1、data选项应始终被声明为一个函数

2、过渡类名的更改

//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: 0;
}

.v-leave-from,
.v-enter-to {
  opacity: 1;
}

3、移除keyCode作为 v-on 的修饰符,同时也不再支持config.keyCodes

4、移除v-on.native修饰符

5、移除过滤器(filter)

哔哩哔哩的尚硅谷教学视频-笔记
链接:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=158

标签:name,reactive,对象,setup,特性,person,vue3,ref
来源: https://blog.csdn.net/webtext/article/details/123061587

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有