1、是vue3.0的中的一个新增配置项,值为一个函数。
2、setup是所有composition API(组合式api)展示的舞台。
3、setup函数的两种返回值:
若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)
若返回一个渲染函数:则可以自定义渲染内容。(了解) (不常用)
注意点:
1、尽量不要和vue2.x版本混用。
2、setup不能是一个async函数,因为返回值不再是对象, 而是promise, 模板看不到return对象中的属性。
3、setup执行顺序在beforeCreat,并且在setup中this为undefined
4、setUp(props, contex)接受两个参数
<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>
作用:定义一个响应式数据。
语法:let xxx = ref(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>
作用:定义一个响应式对象。
语法:let xxx = reactive(xxx)
注意点:
<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>
与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>
和计算属性差不多,在vue3中和只是语法上上的改变。
注意点:
//情况一:监视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配置有效
watch是:既要指明监视的属性,也要指明监视的回调。
watchEffect是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
这个函数的功能和计算属性差不多,但是
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
const x1 = sum.value
const x2 = person.age
console.log('watchEffect配置的回调执行了')
})
1、vue3.0中可以继续使用vue2.x中的生命周期钩子,但是有两个被更名:
2、vue3.0也提供了composition API形式的生命周期钩子,与vue2.x钩子对应关系如下:
创建一个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>
<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>
toRaw
作用:将一个由reactive生成的响应式对象转为普通对象。
使用场景:
markRaw
作用:标记一个对象,使其永远不会再成为响应式对象。
应用场景:
作用:创建一个自定义的 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>
作用:实现祖与后代组件间通信
套路:父组件有一个 provide 选项来提供数据,后代组件有一个 inject 选项来开始使用这些数据
具体写法
祖组件中:
setup(){
......
let car = reactive({name:'奔驰',price:'40万'})
provide('car',car) // 给自己的后代组件传递数据
......
}
后代组件中:
setup(props,context){
......
const car = inject('car') // 拿到祖先的数据
return {car}
......
}
isRef: 检查一个值是否为一个 ref 对象。
isReactive: 检查一个对象是否是由 reactive 创建的响应式代理。
isReadonly: 检查一个对象是否是由 readonly 创建的只读代理。
isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理。
在Vue2中: 组件必须有一个根标签
在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中
好处: 减少标签层级, 减小内存占用
Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。
等待异步组件时渲染一些额外内容,让应用有更好的用户体验
使用步骤:
异步引入组件
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>
//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;
}
哔哩哔哩的尚硅谷教学视频-笔记
链接:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=158