携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情
setup
1.setup 函数是Vue3新的配置项
2.是使⽤组合API的前提,数据、⽅法都要放到 setup 函数⾥声明
3.写法:
在setup里面声明变量和方法,再return出去,通过在插值语法在变量中访问这些变量和方法
<script>
export default {
name: "Setup",
props: {
msg: String,
},
setup() {
const name = "张三";
const age = "14";
function sayHello() {
alert(`你好,我是${name},今年${age}岁了`);//这边不用this是因为这个变量都在这个setup作用域里面
}
return {
name,
age,
sayHello,
};
},
};
</script>
4.剖析setup函数的执⾏时机和两个参数
- 执⾏时机(setup在所有周期函数之前执行)
在⽣命周期函数 beforeCreate 之前执⾏⼀次,⽽且 setup 函数没有 this - 两个参数 props:接收⽗组件的值,是⼀个对象 context:上下⽂对象 触发⾃定义事件
<script>
export default {
name: "SetupMore",
props: ["mess"], //接收父组件的值
emits: ["miaozai"], //需要emits声明才能在setup中使⽤
//在⽣命周期函数 beforeCreate 之前执⾏⼀次
// beforeCreate(){
// console.log('=========beforeCreate========')
// },
// vue3触发
setup(props, context) {
// console.log("========setup====")//在⽣命周期函数 beforeCreate 之前执⾏⼀次
console.log(this); //⽽且 setup 函数没有 this
console.log(props.mess);
function clickMe() {
context.emit("miaozai", "我是⼦组件的值,我现在发给父组件");
}
return {
clickMe,
};
},
// vue2触发自定义事件
mounted() {
this.$emit("miaozai", "我是子组件传过来的值");
},
};
</script>
实现数据的响应式—ref函数
1.定义
定义⼀个响应式的数据
2.基本类型数据
1.引⼊ ref 函数
import { ref } from "vue";
2.创建⼀个包含响应式数据的引⽤对象(ref 对象)
let name = ref("张三");
let age = ref(18);
3.操作数据
function changePerson() {
name.value = "李四";
age.value = "19";
}
3.对象类型数据
1.创建⼀个包含响应式数据的引⽤对象(ref 对象)
let obj= ref({
fruit:'苹果',
price:'12'
});
2.操作数据
function changePrice() {
obj.value.price = "24";
}
4.注意事项:
- 可以处理
基本类型数据、数组或者对象类型的数据 - 基本类型数据的响应式是
通过 Object.defineProperty() 实现 - 对象类型数据的响应式是
通过 ES6 中的 Proxy 实现
实现数据的响应式—reactive函数
1.定义:
定义⼀个对象类型的响应式数据(不能处理基本类型数据)
2.写法:
<template>
<div>
<!-- <h1>水果店{{data.fruit}}</h1> -->
<!-- 使用toRef后不需要再用data了 -->
<h1>水果店:{{ fruit }}</h1>
<h1>水果网站:{{ data.website }}</h1>
<h1>
水果品种:
<ul>
<li>{{ data.fruits.a }}</li>
<li>{{ data.fruits.b }}</li>
<li>{{ data.fruits.c }}</li>
</ul>
</h1>
</div>
</template>
<script>
import { reactive, toRef, toRefs } from "vue";
export default {
setup() {
//定义
let data = reactive({
fruit: "水果王",
website: "fruit.com",
fruits: {
a: "苹果",
b: "香蕉",
c: "西瓜",
},
});
// 拿到目标对象的属性
let fruit = toRef(data, "fruit");
return {
data,
fruit,
...toRefs(data), //展开第一层同时也是拿到第一层
};
},
};
</script>
<style>
</style>
3.reactive 和 ref 不同点
- 处理数据类型不同: ref 可以处理基本类型和对象(数组)类型数据, reactive 只能处理对象(数组)类型数据
- 实现原理不同: ref 处理基本类型数据通过Object.defineProperty() 实现, reactive 通过Proxy 实现
- 操作不同: ref 操作数据需要加
.value - 组件数据多时更加趋向使⽤ reactive
computed函数
1.使用:
通过已有的属性计算⽽来,跟vue2.x中的功能原理⼀样,使⽤⽅式有区别
2.代码:
<template>
<div>
<h2>姓:{{ person.firstName }}</h2>
<h2>名:{{ person.lastName }}</h2>
<h2>全名:{{ fullName }}</h2>
<h2>更改:<input type="text" v-model="fullName" /></h2>
</div>
</template>
<script>
// import { ref, computed } from "vue";
import { reactive, computed } from "vue";
export default {
// vue2实现方式
// data(){
// return{
// fistName:'张',
// lastname:'三'
// }
// },
// computed:{
// fullName(){
// return this.fistName+"-"+this.lastName
// }
// }
// vue3实现方式 计算 ref 定义的响应式数据
// setup() {
// let firstName = ref("李");
// let lastName = ref("四");
// const fullName = computed({
// get() {
// return firstName.value + "-" + lastName.value;
// },
// set(value) {
// const arr = value.split("-");
// firstName.value = arr[0];
// lastName.value = arr[1];
// },
// });
// return {
// firstName,
// lastName,
// fullName,
// };
// },
setup() {
let person = reactive({
firstName: "zhang ",
lastName: "san",
});
let fullName = computed({
get() {
return person.firstName + "-" + person.lastName;
},
set(value) {
const arr = value.split("-");
person.firstName = arr[0];
person.lastName = arr[1];
},
});
return {
person,
fullName
};
},
};
</script>
<style>
</style>
watch函数
1.使用:
监听值的变化,执⾏相关的操作,跟vue2.x中的配置⼀样
2.代码:
<template>
<div>
当前的计数:<span>{{ num }}</span> 当前的计数:<span>{{ num1 }}</span>
<button @click="num++">累加</button>
<button @click="num++">累加num1</button>
<br />
当前的计数c:<span>{{ numObj.c }}</span>
<button @click="numObj.c++">累加c</button>
当前的计数d:<span>{{ numObj.d }}</span>
<button @click="numObj.c++">累加d</button>
当前的计数a:<span>{{ numObj.a.ee }}</span>
<button @click="numObj.a.ee++">累加.a.ee</button>
</div>
</template>
<script>
import { ref, watch, reactive } from "vue";
export default {
// vue2实现监听
// data(){
// return{
// num:1,
// }
// },
// watch:{
// num(){
// console.log('num改变了')
// }
// }
// vue3
setup() {
// 监听ref定义的数据
let num = ref(1);
let num1 = ref(3);
// 监听 reactive 定义的数据
let numObj = reactive({
c: 1,
d: 2,
a:{
ee:34
}
});
// 监听⼀个ref定义的数据
// watch(
// num,
// (newValue, oldValue) => {
// console.log("num增加了", newValue, oldValue);
// },
// { immediate: true, deep: true }
// );
// 监听多个ref定义的数据
watch([num, num1], (newValue, oldValue) => {
console.log("num1增加了", newValue, oldValue);
});
// 监听对象类型 bug:原本c的值为1没有打印出来
watch(numObj, (newValue, oldValue) => {
console.log("numObj变化了", newValue, oldValue);
});
// 监听对象中的⼀个基本类型属性
watch(
() => numObj.c,
(newValue, oldValue) => {
console.log("numObj变化了", newValue, oldValue);
}
);
// 监听对象中的⼀些基本类型属性
watch([() => numObj.c, () => numObj.d], (newValue, oldValue) => {
console.log("numObj变化了", newValue, oldValue);
});
// 监听对象中的对象类型属性
watch(numObj.a, (newValue, oldValue) => {
console.log("numObj.c变化了", newValue, oldValue);
});
return {
num,
num1,
numObj,
};
},
};
</script>
<style>
</style>
3.总结实现监听⽣效:
- ref 定义的数据
(1)基本类型数据作为监听值
(2)对象作为监听值,需要加 .value (⽤的少)\ - reactive 定义的数据
(1)对象作为监听值
(2)属性作为监听值,需要放在回调函数中\
setup中的watchEffect函数
1.使用:
在监听的回调函数中使⽤了属性,则监听该属性,不⽤在参数上指明监听哪个属性
2.代码:
<template>
<h1>
当前的计数a:<span>{{ numa }}</span> <br />
当前的计数b:<span>{{ numb }}</span> <br />
</h1>
<button @click="numa++">增加a</button>
<button @click="numb++">增加b</button>
<hr />
</template>
<script>
import { ref, watchEffect } from "vue";
export default {
setup() {
let numa = ref(1);
let numb = ref(1);
// watch ⼿动添加定向的监听属性
// watch([numa, numb], (newValue, oldValue) => {
// console.log("numa或者numb变化了", newValue, oldValue);
// });
// watchEffect ⾃动监听使⽤到的属性
watchEffect(() => {
// let xd = numa.value;
// let xd1 = numb.value;
console.log("watchEffect函数执行了"); //初始化执⾏:watchEffect 会初始化执⾏⼀次
});
return {
numa,
numb,
};
},
};
</script>
<style>
</style>
3.与 watch 的区别
- 属性监听区别:
watch ⼿动添加定向的监听属性
watchEffect ⾃动监听使⽤到的属性\ - 初始化执⾏:
watchEffect 会初始化执⾏⼀次\