——
如果,你努力了但是并没有太大的改观,并不能代表你没有用,
而是代表你在赎罪,你总得为过去的懒散付出点代价,你应该更加努力, 欠的账总会还完,日子总会阳光明媚的!
1.main.js中创建vue实例方法变了
vue2
import Vue form "vue"
import App from xxxx
new Vue({
})
vue3
//引入的不是构造函数,而是createApp工厂函数
import {creatApp} form vue
import App from xxxx
// 创建应用实例对象
const app = creatApp(App)
app.mount(#app)
2.vue3可以没有根标签
3.setup
setup在beforCreat之前执行一次,this指向undefined
a.返回一个对象,对象中属性是setup中定义的变量或者函数(常用)
b.返回一个渲染函数,渲染函数要手动引入下 (不常用)
import {h} from "vue"
return () => h("h1","xxxx") // 渲染函数内容会代替页面中的内容
setup接收两个参数props和context
props: 值为对象,包括组件传输过来并且在当前组件中接收了的属性,需要在setup外面用props:【‘xxx’】接受,在setup中的打印props才有值
context:上下文对象
- attrs:值为对象,包括组件传输过来但是没有在当前组件中接收的属性
- emit: 分发自定义事件的函数,相当于this.$emit,需要像props一样接收下,不然会报警告
- slot: 插槽
4.尽量不要与vue2配置混用
- vue2配置(data、methods、computed)可以访问到setup中的属性、方法
- setup不能访问到vue2的配置
- 如果有重名,setup优先
5.setup不能用async修饰
因为返回值不再是一个对象是一个promise,模板看不到return对象中的属性
6.ref函数
import {ref} from "vue"
setup() {
// 使用ref函数包裹数据,使数据成为ref对象
let name = ref("张三");
let info = ref({
job: "前端工程师",
salary: 30
})
function change () {
name.value = "李四"; // 此时name已经是ref对象,所以修改值要用value
info.value.job = "后端工程师" // info是fef对象,info.value被vue3处理成proxy对象,所以job 不用再.value
}
}
7.reactive 函数
作用: 用来定义对象类型的响应式数据
import {reactive} from "vue"
setup{
const person = reactive({
name: "张三",
hobby: ['抽烟'],
info: {
salary: 30
}
})
function change() {
person.name = "李四";
person.hobby[0] = "学习";
person.info.salary = 40;
}
}
8.vue3使用Proxy实现对象数据的响应式
vue3底层用proxy时设置set,get,deleteProperty时使用了Reflect反射对象,Reflect相当于Object,w3c友谊将Object的属性方法移植到Reflect上,Reflect在执行时会有一个返回值,let b = Reflect.set(a,'name','李四'); console.log(b) => true
const person = {
name: "张三",
age: 16
}
// 通过Reflect操作对象,可以得到一个返回值,在封装中可以减少try...catch的使用
const p = new Proxy(person,{
get(target,properName) {
console.log(`读取了person上的${properName}属性`)
return Reflect.get(person,properName)
}
// 修改和新增都会出发set
set(target,properName,value) {
console.log(`修改了p身上的${properName},修改为value`)
Reflect.set(person,properName,value)
}
deleteProperty(target,properName) {
console.log(`删除了p身上的${,properName}属性`)
return Reflect.deleteProperty(target,properName)
}
})
9.计算属性computed
import {computed} from vue
setup{
...
// 简写形式,此时只能只读
peoson.fullName = computed(() => {
return firstName + '-' + lastName
})
// 完整形式,此时可以读写
person.fullName = computed({
get() {
return firstName + '-' + lastName
};
set(value) {
firstName = fullName.split('-')[0]
lastName = fullName.split('-')[1]
}
})
}
10.监视属性 watch
import {watch} from vue
情况一,监视ref定义的响应式数据
watch(name,(newValue,oldValue) => {},{immediate: true})
情况二,监视多个ref定义的响应式数据
watch([name,school],(newValue,oldValue) => {})
情况三,监视一个reactive定义的数据,此时不能正确或得oldValue,deep配置无效,强制开启深度监视
watch(person,(newValue,oldValue) => {})
情况四,监视reactive定义的数据中的某个属性
watch(() => person.name,(newValue,oldVaule) => {})
情况五,监视reactive定义的数据的多个属性
watch([() => person.name,() => person.age],(newValue,oldVaule) => {})
特殊情况, 监视reactive定义的数据中的某个属性,这个属性是个对象,此时deep配置有效果
10.watchEffect
不用指明具体要监视的属性,回调函数函数中用到哪个数据,就会监视哪个属性,属性变动,执行watchEffect回调,有点像computed计算属性,不过computed注重return的结果,watchEffect不需要return,注重过程
import {watchEffect} from vue
...
let sum = ref(0)
setup() {
watchEffect(() => {
// sum如果变动就会执行打印
const x = sum.value
console.log(xxxxx)
})
}
11.生命周期函数
配置项形式生命周期修改对应关系如下:
| vue2 | vue3 |
|---|---|
beforeDestroy | beforeUnmount |
destroy | unmounted |
vue3中提供了composition API形式的生命周期钩子,对应关系如下:
| composition API | vue2 |
|---|---|
setup() | beforeCreate |
setup() | createed |
onBeforeMount | beforeMount |
onMounted | mounted |
onBeforeUpdate | beforeUpdate |
updated | updated |
onBeforeUnmount | beforeUnmount |
onUnmounted | unmounted |
12.自定义hook
本质是一个函数,将setup中的composition API进行封装 类似于vue2中的mixin 优势:复用代码,让setup中代码逻辑更简单
13.toRef 和 toRefs
作用:创建一个ref对象,其value指向另一个对象的某个属性
语法: const name = toRef(person,'name')
应用: 要将响应式对象中的某个属性单独提供给外部使用
扩展: toRefs和toRef功能一致,但可以批量创建多个ref对象,语法:toRefs(person)
14.shallowReactive与 shallowRef
shallowReactive:只处理对象最外层属性的响应式(浅响应式)
shallowRef:只处理基本数据类型的响应式,不进行对象响应式的处理
15.readonly和shallowReadonly
readonly:让一个响应式数据变为只读(深只读)
shallowReadonly: 让一个响应式数据变为只读(浅只读)
16.toRaw与markRaw
toRef
作用:将一个由reactive生成的响应式对象转为普通对象;
场景:用于读取响应对应的普通对象,对这个对象的所有操作,不会引起页面的更新
markRef
作用:标记一个对象,使其永远不会再成为响应式对象
应用场景:1有些值不应该被设置成响应式,例如第三方类库;2当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能
17.cuntomRef
自定义ref,使用如下案例:
<template>
<input type="text" v-model="message">
<div>{{ message }}</div>
</template>
<script>
import {customRef} from "vue";
export default {
name: 'HelloWorld',
setup(){
function debounce(fn,time) {
let timer = null;
return function() {
let context = this;
let arg = arguments;
if(timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(context,arg)
timer = null
}, time);
}
}
function myRef(value) {
return customRef((track,trigger) => {
return {
set(newValue) {
value = newValue
// 这里自定义了一个防抖函数,如果不好理解可以先去掉防抖功能,直接trigger()
//trigger的作用是触发模板重新渲染
//,因为设置了新的值
debounce(trigger,2000)()
},
get() {
// 调用track函数 告诉get追踪这个值, 必须调用,不然页面中不会展示新的值
track()
return value
}
}
})
}
let message = myRef('hello')
return {
message
}
}
}
</script>
18.provide和inject
用于组建向后代组件传递数据
组件:
import {provide} from 'vue'
...
setup (){
provide('car',car)
}
子孙组件:
import {inject} from 'vue'
...
setup() {
let car = inject('car') // 接收到的数据为响应式
}
19.Suspense
父组件
<template>
<div class="main">
<suspense>
// 默认展示
<template v-slot:default>
<Demo2></Demo2>
</template>
// loading展示
<template v-slot:fallback>
<h1>正在加载中....</h1>
</template>
</suspense>
</div>
</template>
<script>
import { defineAsyncComponent } from 'vue';
// 异步引入组件
const Demo2 = defineAsyncComponent(() => import('./components/Demo2.vue'))
export default {
name: 'App',
components: {
// HelloWorld,
Demo2,
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.main {
width: 100%;
background: blue;
padding: 50px;
}
</style>
子组件
<template>
<div class="demo2"></div>
</template>
<script>
export default ({
name: "demo2",
setup() {
},
})
</script>
<style scoped>
.demo2 {
width: 500px;
height: 500px;
background: orange;
}
</style>
20.Options API和Composition API比较
Options API: 新增或更改一个需求,就要分别在data、methods、watch、computed中进行修改
Composition API: 我们可以更优雅的组织我们的代码、函数,让相关功能的代码组织在一起放到一个hook中