这是我参与「第五届青训营 」笔记创作活动的第13天
常用的Composition API
初识setup
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="sayHello">click</button>
</template>
<script>
export default {
name: 'App',
setup(){
// 数据
let name = '张三'
let age = 18
function sayHello(){
alert('我叫${name}')
}
return{
name,
age,
sayHello
}
}
}
</script>
ref函数
响应式数据的修改
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changInfo">click</button>
</template>
<script>
import {ref} from 'vue'
export default {
name: 'App',
setup(){
// 数据
let name = ref('张三')
let age = ref(18)
function changInfo(){
name.value = '李四'
age.value = 48
}
return{
name,
age,
changInfo
}
}
}
</script>
reactive函数
vue3响应式的实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="text/javascript">
// 源数据
let person = {
name:"张三",
age:18
}
// 模拟vue3中的响应式的实现
const p = new Proxy(person,{
// 有人读取p的某个属性时调用
get(target, p, receiver) {
console.log(`有人读取了p身上的${p}属性`);
return target[p]
},
// 有人修改p的某个属性时调用,或者给p追加某个属性时调用
set(target, p, newValue, receiver) {
console.log(`有人修改了p身上的${p}属性,我要去更新界面了`);
target[p] = newValue
},
// 有人删除p的某个属性时调用
deleteProperty(target, p) {
console.log(`有人删除了p身上的${p}属性,我要去更新界面了`);
return delete target[p]
}
})
</script>
</body>
</html>
reactive对比ref
computed
vue2中的计算属性的实现
<template>
<h1>一个人的信息</h1>
姓<input text="姓" v-model="person.firstName" />
<br>
名<input text="名" v-model="person.lastName" />
<br>
<span>全名:{{fullName}}</span>
</template>
<script>
import {reactive} from "vue";
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: "Demo",
computed:{
fullName(){
return this.person.firstName+'----'+this.person.lastName
}
},
setup(){
// 数据
let person = reactive({
firstName:'王',
lastName:'杰'
})
return {
person,
}
}
}
</script>
<style scoped>
</style>
vue3中计算属性的实现
<template>
<h1>一个人的信息</h1>
姓<input text="姓" v-model="person.firstName" />
<br>
名<input text="名" v-model="person.lastName" />
<br>
<span>全名:{{person.fullName}}</span>
</template>
<script>
import {computed, reactive} from "vue";
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: "Demo",
setup(){
// 数据
let person = reactive({
firstName:'王',
lastName:'杰'
})
//计算属性-------- 没有考虑计算属性被修改的情况
// person.fullName = computed(()=>{
// return person.firstName+'---'+person.lastName
// })
//计算属性完整写法(考虑读和写)
person.fullName = computed({
get(){
return person.firstName+'-'+person.lastName
},
set(value){
let nameArr = value.split('-')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
}
})
return {
person,
}
}
}
</script>
<style scoped>
</style>
一、setup函数
setup:一般返回一个对象,对象的key可以直接使用(也可以返回一个渲染函数)
注意:
- 正常情况下setup不能是一个async函数,因为返回值不再是return的对象, 而是promise,模板看不到return对象中的属性,则组件不会被渲染出来。
- 但是如果配合新增的组件Suspense和异步组件的引用方式,也可以返回一个Promise实例,具体查看 vue3新的组件
二、ref函数
创建一个响应值:ref(“张三”),ref({ name:“张三” }),返回一个RefImpl对象(引用实现的实例化对象,简称引用对象,也叫ref对象)
操作基础类型的响应值:ref(“张三”).value,ref(“张三”).value = “李四”
操作引用类型的响应值:ref({ name:“张三” }).value.name,ref({ name:“张三” }).value.name = “李四”
重点:ref函数返回的是ref对象,当创建的是基础类型的响应式是使用的是object.defineproperty的get与set方法进行数据劫持;当创建的是引用类型时使用的是ES6里面的 Proxy对象 进行代理实现的(实际上是求助了reactive函数)
三、reactive函数
作用:定义一个对象类型的响应式数据(基础类型不能用它)
创建一个响应值:const 代理对象 = reactive(源对象),返回一个代理对象(Proxy的实例化对象,简称Proxy对象)
操作响应值:reactive({ name:“张三” }).name,reactive({ name:“张三” }).name = “李四”
四、回忆vue2 的响应式
1. 实现原理
- 对象类型:进行递归遍历对象的属性进行object.defineproperty的数据劫持
- 数组类型:通过重写更新数组的一系列方法来进行实现拦截。(对数组的变更方法进行包裹)
2. 存在问题
- 新增,删除属性时,界面不会更新
- 直接通过下标修改数组,界面不会更新
- 得采用s e t , set,set,delete,splice等方式进行修改