目录
1、shallowReactive,shallowRef (浅层次的)
2、readonly(只读的) / shallowReadonly (浅层次只读)
一、认识Vue3:
1、Vite:
创建Vue项目的方法。以前我们利用的是webpack,使用vue-cli创建的项目。
## 创建工程
npm init vite-app <project-name>
## 进入工程目录
cd <project-name>
## 安装依赖
npm install
## 运行
npm run dev
2、main.js
3、开发者工具:
二、常用的Composition API(组合式API)
1、setup:
1、是所有Composition API 的表演舞台。
2、理解:VUE3.0中的一个新的配置项,值为一个函数;(vue2以前的配置项:data,mounted,methods,computed,watch)
3、组件中所用到的数据、方法等,均要配置在setup中;
4、setup函数的两种返回值:
1、若返回的是对象,则对象中的属性、方法,在模板中均可以直接使用。
2、若返回的是渲染函数:则可以自定义渲染内容。
5、① vue3向下兼容,在Vue3里面还是可以去使用Vue2的配置项的。② 在组件中同时配置Vue3和Vue2,Vue2的配置项可以去读取Vue3配置项里面的数据或者方法。③ Vue3的配置项不可以去读取到Vue2配置项里面的数据和方法
2、ref:(响应式)
### 语法:
## 引入ref
import { ref } from "vue"
export default {
setup(){
// 数据经过 ref 加工生成一个 引用对象
let name1 = ref("张三")
let age1 = ref(48);
let job = ref({
type: "前端工程师",
salary: "30K"
})
// 修改:
function setData(){
name.value = "李四"
age.value = 89
// 修改对象
console.log(job.value); // proxy
job.value.type = "UI工程师";
job.value.salary = "60K"
}
// 返回一个对象
return {
name,
age,
job,
setData
}
}
}
3、reactive函数
是封装了es6里面的Proxy的函数,reactive是写了具体的proxy的实现。
setup(){
let job = reactive({
type: "前端",
salary: "30k"
})
function changeInfo(){
job.type: "后端";
salary: "60K"
return {
job,
changeInfo
}
}
4、Vue2与Vue3的响应式原理的区别:
Vue2.x的响应式原理
对象:
数组:无法直接根据下标来修改数组:
Vue3.x的响应式原理:
### window里面有一个属性proxy 是代理:
const person = {
name : "张三",
age : 18
}
const p = new proxy(person,{}); // 得到的是一个proxy对象
这样也可以通过p.name / p.age 去获取person的属性,
也可以通过 delete p.name 去删除person里面的属性,
但是这不是响应式的,数据修改了,但是捕获不到数据的改变
Vue3底层:
5、reactive 对比 ref
6、setup的两个注意点:
// 如果外部传递进来数据,而这里没有接收,会出现警告
props:[这里接收外部组件传递进来的数据];
emits:[这里定义父组件里绑定的事件];
setup(props, context){
function testEmit(){
context.emit('hello',666)
}
}
7、computed计算属性:
import {reactive, computed} from 'vue'
export default {
// vue2 的用法:
computed:{
fullName(){
return name1 + name2;
}
}
// Vue3的计算属性: 属于组合式api,不再是配置项
setup(){
let person = reactive({
firstName:"张",
lastName:"三"
})
// 计算属性(简写--只读形式)
let fullName = computed(()=>{
return firstName + lastName
})
// 计算属性(完整写法--读写(也就是可以修改))
let fullName = computed({
get(){
return person.firstName + '-' + person.lastName;
},
set(value){
const nameArr = value.split('-')
person.firstName = nameArr[0];
person.lastName = nameArr[1];
}
})
return {person, fullName};
}
8、数据监听 watch / watchEffect
1.watch
1 监听 ref 定义一个响应式数据的写法
watch(name, (newValue, oldValue) => {
console.log(newValue, oldValue);
})
2 监听 ref 多个响应式数据的写法
watch([name,age], (newValue, oldValue) => {
console.log(newValue, oldValue);
// newValue:[newname,nameage], oldValue:[oldname,oldage]
})
3 监听的配置项
watch(name, (newValue, oldValue) => {
console.log(newValue, oldValue);
},{immediate:true})
4 直接监听 reactive 所定义的一个响应式数据的【全部属性】
let person = reactive({name:"张三", age:18, job:{a:{a1:10}}})
watch(person,(newValue,oldValue)=>{
目前阶段 【无法正确的获取 oldValue 的数据】
reactive 定义的数据,即使对层级的对象,watch也可以监听到,默认【开启了深度监听(关不了)】
})
5 监听reactive所定义的一个响应式数据的【某一个属性】
watch(()=>person.name,(newValue,oldValue)=>{
console.log(newValue, oldValue);
})
6 监听reactive所定义的响应式数据中的【某些属性】
watch([()=>person.name,()=>person.age],(newValue,oldValue)=>{
console.log(newValue, oldValue);
})
7 监听reactive里的一个属性(这个属性仍然是一个对象)
watch(()=>person.job,(newValue,oldValue)=>{
console.log(newValue, oldValue);
},{deep:true}) 此处需要开启深度监听,同时也无法获取到准确的oldValue
2、watchEffect:
watchEffect(()=>{内部逻辑用到哪些数据就触发响应的数据监听})
9、生命周期钩子:
10、hooks 也就是封装的意思(对代码的封装)
11、toRef 和 toRefs
相当于拷贝了一份数据(而且与原来的数据还是相联系的,是响应式的)
...toRefs(person)
三、其他一些 Composition API
1、shallowReactive,shallowRef (浅层次的)
用 shallowReactive 定义的多层次对象的话,数据修改的时候,响应式是浅层次的(只考虑第一层的数据)。
shallowRef 定义的对象类型的数据,也是ref对象,但是内部的value没有去求助proxy,而是直接的object
2、readonly(只读的) / shallowReadonly (浅层次只读)
readonly()是一个函数,接收的是一个响应式数据,它接受的数据表示只读,不允许修改;
shallowReadonly() 它接受的对象数据,浅层次是只读的,深层次的数据仍然是可以修改的;
3、toRaw 与 markRaw
toRaw接受的响应式数据,返回的是最原始的数据,而不是ref或者proxy代理的数据,只能处理reactive定义的数据,而不能处理ref定义的数据
let person = reactive({
name : "张三",
age : 18,
job : {
j1: {
salary : 20
}
}
})
const p = toRaw(person);
// 返回的是一个原始的对象,
{
name : "张三",
age : 18,
job : {
j1: {
salary : 20
}
}
}
markRaw 标记一个对象数据,使其永远不会变为响应式对象;
let person = reactive({
name : "张三",
age : 18,
job : {
j1: {
salary : 20
}
}
})
let car = {name:"奔驰", price:"30w"};
person.car = markRaw(car)
4、customRef 自定义的 ref
- 作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制
5、provide 与 inject (通信)
- 作用:实现祖孙组件间的通信;
- 套路:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这些数据
- 具体写法:
1. 祖组件中: setup(){ ........ let car = reactive({ name:"奔驰", price:"40万" }) provide('car', car) ....... } 2. 孙组件中: setup(){ ......... const car = inject('car'); return { car } ......... }
6、响应式数据的判断
四、Composition Api 的优势
1、Options Api : 使用传统的Options Api 中,新增或者修改一个需求,就需要分别在data,methods,computed里修改。
2、Composition Api 可以更加优雅的组织我们的代码和函数,让相关功能的代码更加有序的组织在一起。
五、新的组件:
2、Teleport:
3、Suspense
异步引入 / 静态引入,网速慢的时候,渲染出现顺序
如果子组件的引入用了异步引入,同时使用了Suspense,则子组件的数据return 可以是一个promise函数