创建vue3项目
- Vue-CLI命令行工具 Vue-CLI版本要在 v4.5以上
$ npm install -g @vue/cli@next
$ vue create my-project
- Vite 快速构建 vite是一个 web 开发构建工具,由于其原生 ES 模块导入方法,它允许快速提供代码。
$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev
vue3新特性
Composition API
写一个组件,vue2.x的写法如下:
需要分别在选项(data、methods、computed...) 中处理逻辑,当我们增加一个需求,逻辑关注点的列表也会增长
当组件越复杂代码越长,就会越碎片化使得理解和维护组件变得困难。另外,在处理单个逻辑关注点时,我们必须不断地“跳转”相关代码的选项块。
如果将同一个逻辑关注点相关的代码配置在一起,按照逻辑进行分割,就会使代码可读性和可维护性都更高。这就是组合式 API解决的
vue2.x 版本给出的解决方案就是 Mixin, Mixin会出现以下问题
- 命名冲突问题
- 不清楚暴露出来的变量的作用
- 逻辑重用到其他 component 经常遇到问题
1、Setup
在创建组件之前执行,一旦 props 被解析,并充当合成 API 的入口点。
注意:setup是在 beforeCreate 之前执行这时还未创建组件实例,因此在 setup 选项中没有 this,也无法访问任何属性。
参数
- props: 组件传入的属性
- context
props
setup 函数中的 props 是响应式的,当传入新的 prop 时,prop将被更新
注意:props数据不能使用 ES6 解构,否则响应式数据失效
当既想使用es6解构,又要是响应式的,可以采用toRefs
context
不是响应式的,可以通过es6语法解构setup(props, {attrs, slots, emit})
- attrs: 获取当前组件标签上所有没有通过
props接收的属性的对象, 相当于this.$attrs - slots: 包含所有传入的插槽内容的对象, 相当于
this.$slots - emit: 用来分发自定义事件的函数, 相当于
this.$emit注意:与props不同,attrs和slots是非响应式的如果你打算根据attrs或slots更改应用副作用,那么应该在onUpdated生命周期钩子中执行此操作
返回值
在setup里返回一个对象,就可以在组件模板中渲染,否则值渲染无效
2、生命周期钩子
setup ()内部调用生命周期钩子:
注意:因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的(setup代替了beforeCreate和created),所以不需要显式地定义它们。
Vue2.x 中的beforeDestroy名称变更成beforeUnmount; destroyed 变更为 unmounted,为了更加语义化,
| 选项式 API | Hook inside setup |
|---|---|
beforeCreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
3、Ref、Reactive、toRefs
Ref、Reactive使声明的变量变成响应式的,在任何地方都生效
不同:
ref主要声明基本数据类型;reactive主要声明对象;
ref也可以用在对象上,但是没有reactive具有高度的响应式,reactive返回的对象是一个深层递归转换的proxy对象
toRefs 将响应式对象转换为普通对象用于将一个 reactive 对象转化为属性全部为 ref 对象的普通对象
import { ref, reactive, toRefs} from 'vue'
const counter = ref(0)
const state = reactive({
foo: 1,
bar: 2
})
const stateAsRefs = toRefs(state)
// ref 和 原始property “链接”
state.foo++
console.log(stateAsRefs.foo.value) // 2
stateAsRefs.foo.value++
console.log(state.foo) // 3
4、watch、watchEffect、computed的用法
watch
参数
- source: 可以支持 string,Object,Function,Array; 用于指定要侦听的响应式变量
- callback: 执行的回调函数
- options:支持 deep、immediate 和 flush 选项。(flush:post/sync如果需要在组件更新后重新运行侦听器副作用)
watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。默认情况下,watch 是惰性的,immediate: true可以立即执行回调函数,deep:true可以深度监听。
watchEffect
- 不需要手动传入依赖
- 默认初始时就会执行第一次, 从而可以收集需要监视的数据
- 无法获取到变化前的值, 只能获取变化后的值
computed
- 直接创建计算值
- 接受 getter 函数并为 getter 返回的值返回一个不可变的响应式ref对象
Teleport(瞬移或者传送门)
将模板移动到 DOM 中 Vue app 之外的其他位置的技术,
主要处理嵌套组件的定位、z-index 和样式的问题。
留意 to 属性跟上面的 id 选择器一致,disabled禁止移动
<teleport to="#some-id" />
<teleport to=".some-class" />
<teleport to="[data-teleport]" />
Suspense
主要用于在进行一个异步加载时,可以先提供一些静态组件作为显示内容,然后当异步加载完毕时再显示.
<template>
<div>
<div v-if="!loading"> ... </div>
<div v-if="loading"> 加载中... </div>
</div>
</template>
上面这种事通过v-if来动态展示loading
使用Suspense就会简单很多,如下图:
#default插槽里面的内容就是你需要渲染的异步组件; #fallback就是你指定的加载中的静态组件。
注意:AsyncComponent组件需要返回一个Promise
<Suspense>
<template #default>
<async-component></async-component>
</template>
<template #fallback>
<div> Loading... </div>
</template>
</Suspense>
Fragment
在 Vue2.x 中, template中只允许有一个根节点:
<template>
<div>
<span></span>
<span></span>
</div>
</template>
复制代码
但是在 Vue3.x 中,你可以直接写多个根节点, 是不是很爽:
<template>
<span></span>
<span></span>
</template>
变更
v-model升级
-
非兼容:用于自定义组件时,
v-modelprop 和事件默认名称已更改:- prop:
value->modelValue; - event:
input->update:modelValue;
- prop:
-
非兼容:
v-bind的.sync修饰符和组件的model选项已移除,可用v-model作为代替; -
新增:现在可以在同一个组件上使用多个
v-model进行双向绑定; -
新增:现在可以自定义
v-model修饰符
vue3的双向绑定
<modal v-model="isVisible"></modal>
<!-- 相当于 -->
<modal :modelValue="isVisible" @update:modelValue="isVisible = $event"></modal>
如果要绑定属性名, 只需要给v-model传递一个参数就行, 同时可以绑定多个v-model:
<modal v-model:visible="isVisible" v-model:content="content"></modal>
<!-- 相当于 -->
<modal :visible="isVisible" :content="content" @update:visible="isVisible" @update:content="content" />
Slot 统一
在 Vue2.x 中具名插槽和作用域插槽分别使用slot和slot-scope来实现, 在 Vue3.0 中将slot和slot-scope进行了合并同意使用。 Vue3.0 中v-slot:
<template v-slot:content="scoped">
<div v-for="item in scoped.data">{{item}}</div> </template>
<!-- 也可以简写成: -->
<template #content="{data}">
<div v-for="item in data">{{item}}</div>
</template>
全局 API
目前vue3的入口写法:
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
createApp返回一个应用实例,该实例初始化后,应用实例 app 可用于挂载具有 app.mount(domTarget)