一、三连问(为什么)
1、为什么需要用 ref ?
- 返回值类型,会丢失响应式
- 如在 setup、computed、合成函数,都有可能返回值类型
- Vue 如不定义 ref,用户将自造 ref,反而混乱
whyRef.vue 组件
- 值类型无处不在
- vue3 是通过 proxy 实现的响应式,但只对引用类型(数组,对象)有效
- 为使得值类型也实现响应式,ref 便出现了
<template> <p>why ref demo {{ state.age }} - {{ age1 }}</p> </template> <script> import { toRefs, reactive, computed } from "vue"; function useFeatureX() { const state = reactive({ x: 1, y: 2, }); return toRefs(state); } export default { name: "whyRef", setup() { const { x, y } = useFeatureX(); const state = reactive({ age: 20, name: "杂货铺", }); const age1 = computed(() => { return state.age + 1; }); setTimeout(() => { console.log(x.value, y.value); state.age = 25; }, 1000); return { state, age1, }; }, }; </script>
2、为何需要 .value ?
- ref 是一个对象(不丢失响应式),value 存储值
- 通过 .value 属性的 get 和 set 实现响应式
- 用于模板、reactive 时,不需要 .value,其他情况都需要
3、为什么需要 toRef 和 toRefs ?
- 初衷:不丢失响应式的情况下,把对象数据 分散/扩展(解构)
- 前提:针对的是响应式对象(reactive 封装的)非普通对象
- 注意:不创造 响应式,而是 延续 响应式
二、Vue3 升级了哪些重要的功能
1、createApp
vue2.x 对比 vue3.0
// vue2.x const app = new Vue({...}) // vue3 const app = Vue.createApp({...})
vue2.x 使用对比 vue3.0
// vue2.x Vue.use(...) Vue.mixin(...) Vue.component(...) Vue.directive(...) // vue3 app.use(...) app.mixin(...) app.component(...) app.directive(...)
2、emits 属性
App.vue 父组件
- 父组件的子组件标签绑定 onSayHello 自定义事件
- info,是子给父要传递的参数
- 注意绑定的时候必须是 @onXxx 的格式,更容易识别出是监听事件(规则)
<template> <HelloWorld @onSayHello="sayHello" /> </template> <script> import HelloWorld from "./components/HelloWorld.vue"; export default { methods: { sayHello(info) { console.log('hello', info); } }, components: { HelloWorld }, }; </script>
HelloWorld.vue 子组件
- setup里面传两个参数
- 第一个参数 props,获取属性
- 第二个参数是一个对象,对象解构之后是 emit 属性
- 之后通过 emit 调用自定义事件,后面用来传参
<template> <p>emits 的使用</p> </template> <script> export default { name: 'HelloWorld', emits: ['onSayHello'], setup(props, { emit }) { emit('onSayHello', 'vue3') } }; </script>
3、生命周期
4、多事件
在 methods 里定义 one two 两个函数
<button @click="one($event), two($event)">Submit</button>
5、Fragment 组件模板
vue2.x 组件模板:多个 html 标签 必须包裹 起来
<template> <div> <h3>Hello Vue3</h3> <p>前端杂货铺</p> </div> </template>
vue3.x 组件模板:不需要包裹
<template> <h3>Hello Vue3</h3> <p>前端杂货铺</p> </template>
6、移除 .async
async 可以实现父子组件数据之间的双向绑定,与 v-model 类似
在 Vue2 中一个组件上只能有一个 v-model,而 .sync 修饰符可以有很多个
// vue2.x <MyComponent v-bind:title.sync="title" />
// vue3.x <MyComponent v-model:tilte="title">
7、异步组件的写法
Vue2.x 写法
new Vue({ components: { 'my-component': () => import('./xxx.vue') } })
Vue 3.x 写法
import { createApp, defineAsyncComponent } from 'vue' createApp({ components: { AsyncComponent: defineAsyncComponent(() => import('./components/AsyncComponent.vue') ) } })
8、移除 filter
以下 filter 在 vue3 中不可用
{{ message | capitalize}} <div v-bind:id="rawId | formatId"></div>
9、Teleport
- 是一种能够将我们的组件 html 结构移动到指定位置的技术
- data 中设置 modalOpen: false
<button @click="modalOpen = true"> 打开全屏模式(使用 teleport) </button> <teleport to="body"> <div v-if="modalOpen" class="modal"> <div> telePort 弹窗(父元素是 body) <button @click="modalOpen = false">关闭弹窗</button> </div> </div> </teleport>
10、Suspense
- 等待异步组件时渲染一些额外内容,让应用有更好的用户体验
<Suspense> <Test1 /> <!-- 是一个异步组件 --> <!-- #fallback 就是一个具名插槽 即 Suspense 组件内部,有两个 slot, 其中一个具名为 falllback --> <template #fallback> Loading... </template> </Suspense>
11、Composition API
- reactive
- ref 相关
- readonly
- watch 和 watchEffect
- setup
- 生命周期钩子函数
不积跬步无以至千里 不积小流无以成江海
点个关注不迷路,持续更新中…