setup
理解:
1.Vue3.0中一个新的配置项,值为一个函数
2.setup是所有Composition API(组合API)表演的舞台
3.组件中所有用到的方法,变量,计算属性,数据等全部配置在里面
4.不要与vue2的配置混合使用,因为他们(data,methods,computed......)可以访问setup中的内容,而setup访问不到vue2的配置。如果配置了vue2的设置,重名了,setup的优先级更高
5.setup不能是一个async函数,因为async函数返回的是一个promis对象,不再是return的对象,因此模板看不到return对象中的东西
setup的两种写法
1.返回值为一个对象,将对象中的属性拿来使用
<template>
<div class="home">
<h1>显示vue3.0的数据和方法</h1>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="sayName()">点击测试vue3.0的方法</button>
</div>
</template>
<script>
export default {
setup() {
// 现在暂时还不考虑响应式数据的问题
// 数据
let name = "李国栋";
let age = 18;
// 方法
let sayName = function () {
console.log(`我的名字是${name},我的年龄是${age}`);
}
return {
name, age, sayName
}
}
}
</script>
2.返回值为一个渲染函数,可以自定义内容
//页面中会显示一个h1标签,标签的内容是"vue3返回渲染函数"
<script>
import {h} from 'vue'
export default {
setup() {
// 返回一个渲染函数
// h相当于document.CreateElement()
return ()=>{return h("h1","vue3返回渲染函数")}
}
}
</script>
3.语法糖(最常用的方法),直接在script标签中加入setup属性,不用导出,直接写代码就能用
<script setup>
import {ref} from "vue"
let msg=ref(“666”)
</script>
<template>
<div>
<p>{{msg}}</p>
</template>
ref函数
作用:定义一个响应式数据
语法:const msg=ref("value")
创建一个包含响应式的数据的引用对象(reference对象)
js操作数据:msg.value
注意:可接收基本数据类型,应用数据类型
基本数据类型:响应式依然靠Object.Property()的set和get完成
引用数据类型:依靠reactive函数
<script setup>
import { computed, ref, reactive } from "vue"
import Box from "./components/Box.vue"
var msg = ref("666")
var arr1 = ref([123456798, 2, 3])
</script>
<template>
<div>
<p>{{arr[0]}}</p>
<p>{{arr1[0]}}</p>
</template>
<style scoped lang="scss">
</style>
reactive函数
作用:定义一个对象类型的响应式数据(基本数据类型用ref函数)
语法:const 代理一个对象=reactive(被代理的对象)接收一个对象或者数组,返回一个代理对象(proxy对象)
注意:
reactive定义的响应式数据是“深层次的”
内部基于ES6的Proxy实现,通过代理对象内部的数据都是响应式的
<script setup>
import { computed, ref, reactive } from "vue"
import Box from "./components/Box.vue"
var msg = ref("666")
var arr1 = ref([123456798, 2, 3])
function fn() {
if (msg.value == "666") {
msg.value = "gaibian";
obj.a = "2222";
arr[0] = "sfs"
console.log("111");
} else {
msg.value = "666"
obj.a = "1111"
arr[0] = "a"
}
}
const obj = reactive({
a: "1111",
b: "dassa"
})
const arr = reactive([{ title: "a", price: 10, count: 1 },
{ title: "b", price: 10, count: 2 },
{ title: "c", price: 10, count: 3 },
{ title: "d", price: 10, count: 4 },
])
//计算属性,和vue2不同的是,不再写到一块,而是分开放置 computed(n1,n2) n1计算的函数 n2(可写可不写)变的时候回调用这个函数
let tool = computed(() => {
return arr.reduce((n1, n2) => {
return n1 + n2.price * n2.count
}, 0)
}, arr)
let fn1 = function (index) {
arr[index].count++
}
</script>
<template>
<div>
<p>{{arr[0]}}</p>
<p>{{arr1[0]}}</p>
<p>{{msg}}</p>
<p>{{obj.a}}</p>
<button @click="fn">dianji</button>
<div v-for="(el,index) in arr">
<p>{{el.title}}</p>
<p>{{el.price}}</p>
<p>{{el.count}}</p>
<button @click="fn1(index)">+</button>
</div>
<p>总价:{{tool}}</p>
</div>
<Box></Box>
</template>
<style scoped lang="scss">
</style>
Vue3.0的响应原理
vue2.0的响应式
-
实现原理
-
对象类型:通过Object.definedProperty()对属性的读取、修改进行拦截(数据劫持)
-
数组类型:通过重写更新数据的一系列方法来实现拦截。(对数组的方法进行了包裹)
Object.defineProperty(data,"count",{ get(){}, set(){} })
存在问题:
- 新增属性,删除属性都不会刷新界面
- 直接通过下标修改数组,界面不会自动更新
let person = { name:"李国栋", age:18 } let p = {}; Object.defineProperty(p,"name",{ get(){ console.log("有人读取数据时调用"); return person.name }, set(value){ console.log("有人修改了数据,我要去更新页面"); person.name = value } })
-
vue3.0的响应式
-
实现原理
-
通过Proxy(代理):拦截对象中任意属性的变化,包括:属性的读写,属性的添加,属性的删除等
-
通过Reflect(反射):对被代理对象的属性进行操作
-
MDN文档中描述的Proxy与Reflect:
-
let person = {
name:"李国栋",
age:18
}
let p = new Proxy(person,{
// 读取
get(target,proname){
// target表示原对象 proname表示对象名
console.log("有人读取了person上的属性",target);
return target[proname]
},
// 修改或者增加
set(target,proname,value){
console.log("有人修改了person上的属性,我要去更新了");
target[proname] = value
},
// 删除
deleteProperty(target,proname){
console.log("有人删除了person上面的属性,我要去调用了");
return delete target[proname]
},
});
计算属性computed()
计算属性:和vue2不同的是,不再写到一块,而是分开放置 computed(n1,n2) n1计算的函数 n2(可写可不写)变化的时候会调用这个函数。功能和vue2相同,会缓存计算结果
写法:
let 计算的属性 = computed(计算的函数,监听的变量)
let tool = computed(()=>{})
案列:
<script setup>
import { computed, ref, reactive } from "vue"
import Box from "./components/Box.vue"
var msg = ref("666")
var arr1 = ref([123456798, 2, 3])
function fn() {
if (msg.value == "666") {
msg.value = "gaibian";
obj.a = "2222";
arr[0] = "sfs"
console.log("111");
} else {
msg.value = "666"
obj.a = "1111"
arr[0] = "a"
}
}
const obj = reactive({
a: "1111",
b: "dassa"
})
const arr = reactive([{ title: "a", price: 10, count: 1 },
{ title: "b", price: 10, count: 2 },
{ title: "c", price: 10, count: 3 },
{ title: "d", price: 10, count: 4 },
])
//计算属性,和vue2不同的是,不再写到一块,而是分开放置 computed(n1,n2) n1计算的函数 n2(可写可不写)变的时候回调用这个函数
let tool = computed(() => {
return arr.reduce((n1, n2) => {
return n1 + n2.price * n2.count
}, 0)
}, arr)
let fn1 = function (index) {
arr[index].count++
}
</script>
<template>
<div>
<p>{{arr[0]}}</p>
<p>{{arr1[0]}}</p>
<p>{{msg}}</p>
<p>{{obj.a}}</p>
<button @click="fn">dianji</button>
<div v-for="(el,index) in arr">
<p>{{el.title}}</p>
<p>{{el.price}}</p>
<p>{{el.count}}</p>
<button @click="fn1(index)">+</button>
</div>
<p>总价:{{tool}}</p>
</div>
<Box></Box>
</template>
<style scoped lang="scss">
</style>