Vue3的心得(为了更好的服务ts)
1.ref和reactive的区别
2.watch和computed,watchEffect
3.获取dom结点
4.子向父传数据,父向子传数据
5.props和emit
6.动态组件
7.阻止冒泡行为
8.插槽
9.provide和inject
10.异步组件
11.组合式函数
12.自定义指令
13.teleport
14.Suspense
vue2得各种写法可以访问vue3
- 如果引入一个包,只用了其中一部分,那么通过Tree-shaking就可以把没有利用到的都清除掉。
// 创建应用实例对象 类似于Vue2的vm(比vm更加轻)
const app = createApp(App)
- setup函数即可以返回一个对象,同时也可以返回一个函数(渲染函数)
// 返回一个对象
return {
a,
age,
getAge,
};
import {h}from 'vue'
// 返回一个渲染函数
return () => h("h1", "abc");
- 引用setup数据的时候,并不需要用this
setup函数
- setup的执行时期是在beforeCreate之前,且只执行一次。
- setup(props,context)可以添加两个参数,props就是可以获得自定义属性,context可以获得emit,slot等操作。
emit在向父组件传值得时候,需要通过emits选项来确定传出去的值是什么。
h函数
1.渲染函数 return () => h("h1", "abc");
ref函数(通过get和set实现响应式)
- 定义一个响应式的数据
- 通过引用ref,然后进行.value进行响应式的修改值。
- 即可以是基本数据类型的数据,也可以是对象类型的数据。
import { ref } from "vue";
let a = ref(10);
let age = ref(5);
function getAge() {
a.value = 11;
age.value = 10;
}`person.fullAge = computed(() => {
return person.age + person.name;
});`
reactive函数(通过proxy,内部通过reflect来实现响应式)
- 是对象类型的数据
- 获取数据的时候不再需要.value,直接.键名就可以。
- 这里不再需要$set就可以直接修改对象的值或者添加值。
ref和reactive的区别
- 首先ref通常对基本数据类型进行响应式(对象也可以,但是不常用),reactive对对象进行响应式。
- ref通过的是Object.defineProperty进行响应式,reactive通过的是proxy(代理对象)。
computed和watch
computed函数
这个存在数据缓存以及不要在computed中使用异步函数。
如果你想要返回一个对象的话,那么箭头函数就得这么写(()=>({}))
- 我们通过一个元素来获取computed来重新获取的数据,默认下是get()。
//computed中间是一个回调函数
const value = computed(() => {
// 默认是get
return x.a.b;
});
2.如果我们想直接修改computed值的话就要通过set方法。
const value = computed({
//默认情况下
get() {
return x.a.b;
},
// value = 10时候,调用这个。
set(value) {
x.a.b = value + 1;
},
});
watch函数
普通数据类型 watch(基础数据类型,回调函数,配置对象)
引用数据类型 watch(()=>(return 引用数据里面的值),回调函数,配置对象)
watch(
//侦听基础数据类型的时候
y,
(newValue, oldValue) => {
console.log(newValue, oldValue);
}
);
//侦听对象
watch(
//如果是对象的话就写成getter函数,否则有问题,同时还可以用watchEffect来进行
() => x[0].a,
(a) => {
console.log(a);
}
);
watchEffect
可以替换watch侦听引用数据类型
可以根据一个数据发生变化之后里面进行异步操作等
如果你想在一个数据展现为true之后立马访问dom的话,那么配置项对象中配置 flush: 'post'
watchEffect(() => {
//这个可以实例创建之后直接执行一次。
//可以代替watch侦听引用数据类型的变化。
const sum = agE.value;
console.log("123" + sum);
});
const y = ref(10)
//只要y发生变化那么就会执行一次watchEffect
watchEffect(async () => {
const data = await a1(y.value);
console.log(data);
});
dom结点
<input ref='koko'/>
const koko = ref(null);
console.log(koko.value.innerHTML)
props
父向子
//在子组件上面添加这个
defineProps(['title'])
//如果需要添加数据类型的时候
const props = defineProps({
foo: String
})
子向父
1.第一种写法
//子组件
<button @click='$emit('自定义的事件名')'/>
//父组件
<hoho @自定义的事件名='change'/>
2.第二种写法
//子组件
defineEmits(['enlarge-text'])
//父组件
<hoho @enlarge-text='change'/>
props和emit
defineEmits和defineProps中间的参数都是数组
如果在模块中emit的话可以使用$emit,如果在script中的话那么就定义一个emit来使用。
import {defineEmits,defineProps} from 'vue'
1.不校验版本
const emit = defineEmits(['showshow'],1)
2.校验版本
const emit = defineEmits((value)=>{
if(value){
console.log(123)
//必须得有返回值
return true
}
})
1.不校验版本
const prop= defineProps(['value'])
2.校验版本
const emit = defineProps({
value:String
})
function addMessage(){
emit('showshow',{
name:'li',
age:10
})
}
动态组件
<button @click="qwe='xixi'">+</button>
<component :is='value[qwe]'></component>
import help from "@/components/help.vue";
import xixi from '@/components/xixi.vue'
let qwe = ref('help')
let value = {
help,
xixi
}
阻止冒泡行为
- 我们在组件上添加一个点击事件,组件内部也添加一个点击事件,如果内部点击得话,那么会触发冒泡事件。
此时会触发冒泡行为
//组件上
<component :is='value[qwe]' @click="add"></component>
//组件内部
<button @click="addMessage">add</button>
阻止冒泡得行为如下:
<script>
// 使用普通的 <script> 来声明选项
export default {
inheritAttrs: false
}
</script>
插槽
1.普通插槽
<component :is='value[qwe]'>
1
</component>
//组件内部就显示1
<slot/>
2.具名插槽
<component :is='value[qwe]'>
//使用模板
<template #footer>
1
</template>
</component>
<slot name='footer'/>
3.带值插槽
<component :is='value[qwe]'>
<template #footer="obj">
{{obj.title}}
</template>
</component>
<slot name='footer' title='天气不错'/>
provide和inject
可以解决祖和孙进行数据的交互
多依赖的话 可以创建一个key.js的文件 然后里面存放我们需要注入的内容
// keys.js
export const myInjectionKey = Symbol()
// 在供给方组件中
import { provide } from 'vue'
import { myInjectionKey } from './keys.js'
provide(myInjectionKey, { /*
要提供的数据
*/ });
// 注入方组件
import { inject } from 'vue'
import { myInjectionKey } from './keys.js'
const injected = inject(myInjectionKey)
祖组件
provide('location',{
x:'10',
y:'20'
})
孙组件
const {x,y} = inject('location')
异步组件
基于的原理就是promise
import xixi from '@/components/xixi.vue'
const great = defineAsyncComponent(()=>{
return new Promise((resolve)=>{
setTimeout(()=>{
resolve(xixi)
},2000)
})
})
组合式函数
把我们需要的内容全部抽离出来重新组装成一个函数
hooks函数
- 封装一个hooks文件夹,然后通过export default function(){}
1.event.js
import { onMounted, onUnmounted } from "vue";
export function useEventListener(target,event,callback){
onMounted(()=>{
target.addEventListener(event,callback)
})
onUnmounted(()=>{
target.removeEventListener(event)
})
}
2.mouse.js
import {ref } from "vue"
import {useEventListener} from '@/use/event.js'
export function useMouse(){
const z = ref(0)
const y = ref(0)
useEventListener(window,'mousemove',function(event){
z.value = event.pageX
y.value = event.pageY
})
return {z,y}
}
3.引入该公用函数
import {useMouse} from '@/use/mouse.js'
const {z,y} = useMouse()
自定义指令
组合式函数的写法就是:
const vFocus = {
mounted:(el)=>{
el.focus();
}
}
非组合式写法:
directives: {
// 在模板中启用 v-focus
focus: {
/* ... */
}
}
teleport
模态框十分适用
- 解决定位不到我们需要的位置的时候,可以使用这个方法,比如我们需要定位到body的身上的时候,可以使用这个标签。
父元素有position,但是模态框并不受这个影响。
<div class="mask1">
1.定位到我们想要的body身上。
<teleport to='body'>
<div class="mask" v-if="show">
<div class="content">
<button @click="show=false"></button>
</div>
</div>
</teleport>
</div>
Suspense
- 这个是为了服务异步组件时候来使用。
- 如果我们异步组件加载失败的话,那么可以通过这个标签来加载备用内容。
<Suspense>
//如果great组件加载失败的话,那么可以一直是loading
<great :value='{z,y}'/>
<template #fallback>
<h1>loading</h1>
</template>
</Suspense>
toRef函数
- 可以获取某对象的某属性的值,同时该属性的值变化的时候,自己的值也会变化。
toRefs函数
- 可以将一个对象类型的数据,将其属性全部展现为一个又一个的分支。
import {toRefs} from ‘vue’
let person = reactive({
age: 10,
name: “li”,
hobby: [1, 2, 3],
a: {
b: {
c: 10,
},
},
});
return {
…toRefs(person),
};
## shallowReactive函数
- 就是浅拷贝数据对象。
- 让自己自增,页面不会显示,但是让别的自增,之前自己的自增就会显现出来。
`让c自增页面不会显示,但是自增age的话c就会在页面显示最新的数据。`
```javascript
let person = shallowReactive({
age: 10,
name: "li",
hobby: [1, 2, 3],
a: {
b: {
c: 10,
},
},
});
shallowRef函数
- 数据不需要修改的时候,可以用这个。(也就是对象数据的时候)
readonly函数
- 使数据变成可读的,不能进行修改。
person = readonly(person);
shallowReadonly函数
- 也就是数据对象的第一层不能够修改,深层次的可以修改。
toRaw函数
- 可以把响应式数据reactive,还原成最初始的数据。
markRaw函数
- 指定添加的数据不具有响应式。
##customRef函数
- 创建一个自定义的rf,并对其依赖项跟踪和更新触发进行显式控制。
function myRef(value) {
// 闭包 返回一个函数,参数是一个函数
return customRef((track, trigger) => {
// 返回一个对象
return {
// 第一步
get() {
// 第四步
// 通知vue追踪数据的变化
track();
return value;
},
// 第二步
set(newValue) {
value = newValue;
// 延迟解析模板
setTimeout(() => {
// 第三步
// 通知vue重新解析模板
trigger();
}, 2000);
},
};
});
}
// 自定义函数的返回参数
let data = myRef(123);
provide和inject函数
- 实现祖孙组件间通信
- 父组件有一个provide选项来提供数据,子组件有一个inject选项来使用数据。
响应式数据的判断
fragment组件
- 虚拟元素,也就是可以不需要根标签了。
teleport组件
- teleport是一种能够将我们的组件html结构移动到指定位置的技术。
Suspense组件
<!-- 异步组件 -->
<Suspense>
<!-- 成功得时候 -->
<template v-slot:default> </template>
<!-- 失败的时候 -->
<template v-slot:fallback> </template>
</Suspense>
import { defineAsyncComponent } from "vue";
异步组件
const child = defineAsyncComponent(() => import("./"));
同时这个可以配合promise对象来使用。
其他得一些修改
// 等同于vue.prototype,往原型链上面添加值。
app.config.globalProperties;