Vue3 Day1Day2-Vue3优势ref、reactive函数
Day1
1.1 Vue3的优势
更容易维护
组合式API
更好的TypeScript支持
更快的速度
重写diff算法
模板编译优化
更高效的组件初始化
更小的体积
良好的TreeShaking
按需引入
更优的数据响应式
Proxy
setup中不存在this,如果想直接获取节点,就得放在onMounted(一个函数代码) 里面,记得引入它
Day2 ref、reactive
2.1 ref函数
定义:接收简单类型或者复杂类型的数据传入并返回一个响应式的对象
底层原理:如果包裹基本数据类型,底层是函数中的getter和setter;如果包裹引用数据类型,底层是proxy,原理是内部 “ 求助 ” 了Vue3.0中的一个新函数—— reactive函数 这个函数实际就是使用了vue3的响应式原理中的proxy。
ref基本类型用法
<template> <div> <h1>公主的信息</h1> <h2>姓名:{{name}}</h2> <h2>年龄:{{age}}</h2> <h2 v-for="(item,index) in hobby" :key="index">爱好:{{item}}</h2> <button @click="changeAge">年龄增加按钮</button> </div> </template> <script setup> import { ref } from 'vue' let name = "公主"; let age = ref(12); let hobby = ['美甲', '逛街'] let changeAge = () => { // 写法:xxx.value age.value++ console.log('age=>', age); } </script>
ref引用类型用法
<template> <div> <h1>公主的信息</h1> <h2>姓名:{{res.name}}</h2> <h2>年龄:{{res.age}}</h2> <h2 v-for="(item,index) in hobby" :key="index">爱好:{{item}}</h2> <button @click="changeAge">年龄增加按钮</button> </div> </template> <script setup> import { ref } from 'vue' let res = ref({ name: '公主', age: 12, }) let hobby = ['美甲', '逛街'] let changeAge = () => { res.value.age++ console.log('age=>', res.value.age) } </script>
2.2 reactive函数
定义:接收复杂类型数据的参数传入并返回一个响应式的对象
语法:不需要使用 xxx.value得到想要的值,
注意:
不能对基本数据类型产生响应性,会出现警告
reactive的丢失响应性以及解决办法
reactive的基本使用
<template> <div> <h1>公主的信息</h1> <h2>姓名:{{res.name}}</h2> <h2>年龄:{{res.age}}</h2> <h2 v-for="(item,index) in hobby" :key="index">爱好:{{item}}</h2> <button @click="changeAge">年龄增加按钮</button> </div> </template> <script setup> import { reactive } from 'vue' let res = reactive({ name: '公主', age: 12, }) let hobby = ['美甲', '逛街'] let changeAge = () => { // 不用 .value这种写法 res.age++ console.log('age=>', res.age) } </script>
reactive的响应性
<template> <div> <h1>公主的信息</h1> <h2>姓名:{{res.name}}</h2> <h2>年龄(复杂类型的响应性):{{res.a.b.age}}</h2> <h2>简单类型的响应性:{{count}}</h2> <h2 v-for="(item,index) in hobby" :key="index">爱好:{{item}}</h2> <button @click="change">增加按钮</button> </div> </template> <script setup> import { reactive } from 'vue' let count = reactive(13) let res = reactive({ name: '公主', a: { b: { age: 12, } } }) let hobby = ['美甲', '逛街'] let change = () => { count++ //报出警告 // 不用 .value这种写法 // res.a.b.age++ //这个不能和 count++同时出现看效果 } </script>
reactive丢失响应性并解决:
reactive丢失响应性,引用数据类型的值是存在堆里面,其指针存在栈里面,通过reactive包裹进行赋值(数组,对象,解构),产生新的地址(是一个普通对象),丢失原来响应式对象的引用地址
<template> <div> <!-- <h1>{{arr}}</h1> --> <!-- <h1>{{res.newArr}}</h1> --> <h1>{{num}}</h1> <h1>{{res}}</h1> <button @click="showInfo">按钮</button> </div> </template> <script setup> import { reactive, ref } from 'vue' // 问题:reactive丢失响应性 // let arr = reactive([]) // let showInfo = () => { // let res = [1, 2, 3, 4, 5, 6] // // reactive 定义数据(必须是对象),是直接调用 reactive 方法处理成响应式对象。 // // 如果重新赋值,就会丢失原来响应式对象的引用地址,变成一个新的引用地址, // // 这个新的引用地址指向的对象是没有经过 reactive 方法处理的,所以是一个普通对象,而不是响应式对象。 // // 解构同理 // arr = res // console.log('arr=>', arr); // } // 解决办法1:不简洁,不推荐 // let res = reactive({ // newArr: [] // }) // let showInfo = () => { // let arr = [1, 2, 3, 4, 5, 6] // res.newArr = arr // console.log('res.newArr', res.newArr); // } // 解决办法2:ref来解决,推荐 // let res = ref({ // newArr: [] // }) // let showInfo = () => { // let arr = [1, 2, 3, 4, 5, 6] // res.value.newArr = arr // } // 解决办法3:产生页面更新会触发reactive响应,不推荐 let res = reactive([]) let num = ref(1) let showInfo = () => { let arr = [1, 2, 3, 4, 5, 6] num.value++ //ref操作后,页面重新刷新,所以会让reactive产生响应性 res = arr } </script>
2.3 ref对比reactive
ref和reactive的响应性是深层次的
基本数据类型或者引用数据类型推荐用ref,引用数据类型推荐用reactive
reactive包裹引用数据类型,不需要用 xxx.value,不能对基本数据类型产生响应性,会出现警告
2.4 ref操作dom节点
<template>
<div>
<h1>公主的信息</h1>
<h2 ref="nling">年龄:{{age}}</h2>
<h2 v-for="(item,index) in hobby" :key="index">爱好:{{item}}</h2>
<button @click="change">变化按钮</button>
</div>
</template>
<script setup>
import {
ref
} from 'vue'
let age = ref(12)
// 推荐这种写法
let nling = ref()
let hobby = ['美甲', '逛街']
let change = () => {
age.value++
// ref操作dom节点
nling.value.style.color = '#f60'
}
</script>
<style scoped>
</style>
2.5 delete操作符
2.6 父传子静态传值
非语法糖父传子
父组件
<template> <div> <HelloWorld name="白泽" school="观音大士学府"></HelloWorld> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { setup() { }, components: { HelloWorld } } </script>
子组件
<template> <h1>{{ name }}</h1> <h1>{{ school }}</h1> </template> <!-- setup取代了export default --> <script> export default { props: ['name', 'school'], setup() { } } </script> <style scoped> .read-the-docs { color: #888; } </style>
语法糖父传子
父组件
<template> <div> <HelloWorld name="白泽" school="观音大士学府"></HelloWorld> <!-- <HelloWorld school="观音大士学府"></HelloWorld> --> </div> </template> <script setup> import HelloWorld from './components/HelloWorld.vue' </script>
子组件
<template> <h1>{{ name }}</h1> <h1>{{ school }}</h1> <button @click="print">打印按钮</button> </template> <!-- setup取代了export default --> <script setup> // 接收父组件传过来的数据 // 写法1: // defineProps(['name', 'school']) // 写法2: // defineProps({ // name: String, // school: String // }) // 写法3: // defineProps({ // name: { // type: String, // default: '哪吒' // }, // school: String // }) // 写法4: let res = defineProps(['name', 'school']) //只读,不可修改或添加 let print = () => { console.log('res=>', res); //props接收的值是静态的,当父组件传动态的值的时候,props是拿不到的,只能通过watch进行监听 } </script> <style scoped> .read-the-docs { color: #888; } </style>