VUE3 ONE-PIECE
1.初识VUE3
1.使用vite创建vue3工程
npm init vite-app vue3_test_vite
2.工程结构
VUE3不再引入vue构造函数而是 引入一个 createapp 的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
//创建app实例对象类似于vm 但是app比vm更加轻
//mount 挂载 unmount 卸载
ceateApp(App).mount('#app')
原VUE2
import Vue from 'vue'
new Vue({
render: (h)=> {return h('App')}
}).$mount('#app')
3.templete标签
可以直接 写标签不用再在 templete 里包 div
2.常用的composition API (组合式API)
compositionAPI 太抽象了 兄弟们
1.拉开序幕的setup
vue3 的新配置项 setup 是所有的 composition API 表演的舞台
vue3 中所有的: data method computed 均要配置到setup里
setup 的返回值可以直接在 模板 、方法 中调用
setup 可以返回一个 渲染函数
setup() {
let name = 'zs';
let age = 12;
function showName() {
alert(name)
}
return { //setup的返回值
name,
age,
showName
}
}
注意 : 1. 不要将 vue2 与 vue3 混用,当两者发生冲突是会以vue3为主
2.setup 不能是一个 async 函数,因为其返回值不是return里的对象而是一个promise
2.ref函数
定义一个相应式数据
1.普通数据 与 响应式 数据
傻缺儿子: 非相应式数据
setup() {
let name = 'zs';
let age = 12;
}
响应式数据:
setup() {
let name = ref('zs');
let age = ref(12);
}
ref 加工后的数据变为: ref把数据包转成对象的形式
RefImpl {__v_isShallow: false, dep: Set(1), __v_isRef: true, _rawValue: 'zs', _value: 'zs'}
RefImpl {__v_isShallow: false, dep: Set(1), __v_isRef: true, _rawValue: 12, _value: 12}
从单词层面理解ref : RefImpl = reference + implement 引用实现对象 简称 引用对象
引用 实现
通过objectpropoty 与 getter、setter 实现
下面让我们打开 RefImpl 进一步观察
RefImpl {__v_isShallow: false, dep: Set(1), __v_isRef: true, _rawValue: 'zs', _value: 'zs'}
|----dep: Set(1) {ReactiveEffect}
|----__v_isRef: true
|----__v_isShallow: false
|----_rawValue: "zs"
|----_value: "zs"
|----value: (...)
|----[[Prototype]]: Object
|----constructor: class RefImpl
|----value: (...)
|----get value: ƒ value()
|----set value: ƒ value(newVal)
|----[[Prototype]]: Object
这里我们看到了 getter 与 setter 可以确定 ref 是通过数据劫持来实现响应式
现在我们知道要改变页面中的数据必须使用 <数据>.value 的形式 但模板中使用数据 不需要 <数据>.value 因为vue已经帮你用了.value
ref包裹对象
setup() {
let name = ref(“zs”);
let age = ref(12);
let job = ref({
type: ‘前端工程师’,
salary: ‘2K’
})
function showName() {
// alert(name)
console.log(name,age,job.value);
}
可以看到输出的job.value
Proxy {type: '前端工程师', salary: '2K'}
|----[[Handler]]: Object
|----[[Target]]: Object
|----[[IsRevoked]]: false
他并没用将 job 对象中的每个 属性都用 ref 包裹而是用了 Proxy 的形式,并且我们使用 job 中的属性只要 job.value.type 不要 job.value.type.value 因为元素不在用 refimpl 包裹
具体要如何 用到 proxy 我们看到下一小节
3.reactive函数
定义一个 对象类型 的响应式数据
ref 即可 用到 对象类型 又可用到 普通类型
那么问题来了: 为什么还用reactive呢?
let job1 = reactive({
type: "前端工程师",
salary: "2K",
});
我们可以在定义数据时做这样的处理 :
let person = reactive({
name: "zs",
age: 10,
job: {
type: "前端工程师",
salary: "10k",
},
});
于是在修改数据时我们就要这样处理 :
function showName() {
// alert(name)
person.name = "张三",
person.age = 100,
person.job.type = "UI",
person.job.salary = "20K";
console.log(person);
}
于是我们就不用在person.value.<属性>了 确实在这里我还有一些疑惑(这也没方便多少呀?) 但是老师说了 后面会解决
4.vue3里的响应式原理
1.下回顾一下vue2 里的响应式原理 :
对象类型 通过definePropoty()对属性的读取、修改进行拦截(数据劫持)
数组类型 通过重写数组的方法进行拦截
总而言之就是要调用 对象上 的方法使其可以检测到数据的改变
this.$set() 使得修改数据得到检测 其实还有Vue.set()
同时还有我们没讲到的 $delete 检测删除
修改数组
也可以用$set(<数组>,<索引>,<值>)
或者<数组>.splice(开始的索引,删除几个,值)
存在问题 :删除或者新增元素不会更新
2.vue3的响应式原理 :
git强推 直接覆盖远程仓库:
方法二:强推
即利用强覆盖方式用你本地的代码替代git仓库内的内容
git push -f origin master
模拟vue2
我们可以看到在这里 无法用 delete 和 添加属性
小知识 //#region //#endregion 强制折叠
模拟vue3
//模拟vue3响应式
const p = new Proxy(person, {
get(target, propName) {
console.log(`有人读取了p身上的${propName}属性`);
return target[propName]
},
set(target, propName, value) {
console.log(`有人修改了p上的${propName}属性`);
target[propName] = value
},
delete(target, propName) {
console.log(`有人删除了p上的${propName}属性`);
delete target[propName]
}
})
下面再用介绍一下 reflexct
reflect与Object有着差不多的操作 reflect有返回值 如果要reflect进行错误处理跟加方便 而Objcet要进行try catch包裹
Reflect.defineProperty(p, 'name', {
get() {
console.log('有人读取了name');
return person.name
},
set(value) {
console.log('@@@有人修改了name');
person.name = value
}
});
Reflect.defineProperty(p, 'age', {
get() {
console.log('有人读取了age');
return person.age
},
set(value) {
console.log('@@@有人修改了age');
person.age = value
}
})
reflect 模拟
const p = new Proxy(person, {
get(target, propName) {
console.log(`有人读取了p身上的${propName}属性`);
return Reflect.get(target.propName)
},
set(target, propName, value) {
console.log(`有人修改了p上的${propName}属性`);
Reflect.set(target, propName, value)
},
deleteProperty(target, propName) {
console.log(`有人删除了p上的${propName}属性`);
return Reflect.deleteProperty(target, propName)
//返回Reflect.deleteProperty(target, propName)的结果否者返回undefind
}
})
用reflet 可以返回成功或者失败 也就可以更方便的进行 错误处理