createApp()
js
// 内敛根组建
import { createApp } from 'vue'
const app = createApp({})
// 导入根组建
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount()
js
import { createApp } from 'vue'
const app = createApp(/* ... */)
const vm = app.mount('#app')
vm.unmount() // 在需要卸载应用时,调用
app.unmount() 可以卸载局部组件,而不影响整个应用,下面是手动卸载
js
import { defineComponent } from 'vue'
export default defineComponent({
methods:{
handleUnmount(){
this.$el.parentElement.removeChild(this.$el)
this.$destroy()
}
}
})
app.component()
js
import { createApp } from 'vue'
const app = createApp({})
// 得到一个已注册的组件
const MyComponent = app.component('my-component')
app.directive()
js
import { createApp } from 'vue'
const app = createApp({})
// 注册(对象形式的指令)
app.directive('my-directive', {/* 自定义指令钩子 */})
// 注册(函数形式的指令)
app.directive('my-directive', () => {})
// 得到一个已注册的指令
const myDirective = app.directive('my-directive')
<template>
<input v-focus />
</template>
<script setup>
// 在模板中启用 v-focus
const vFocus = {
mounted: (el) => el.focus()
}
</script>
在没有使用 <script setup> 的情况下,自定义指令需要通过 directives 选项注册:
export default {
setup() {},
directives: {
// 在模板中启用 v-focus
focus: {}
}
}
全局注册
const app = createApp({})
// 使 v-focus 在所有组件中都可用
app.directive('focus', {})
一个指令的定义对象可以提供几种钩子函数 (都是可选的):
const myDirective = {
// 在绑定元素的 attribute 前
// 或事件监听器应用前调用
created(el, binding, vnode, prevVnode) {
// 下面会介绍各个参数的细节
},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode, prevVnode) {}
}
传参,和接受参数
<div v-example:foo.bar="baz">
下面是上述binding参数打印的值
{
arg: 'foo',
modifiers: { bar: true },
value: /* `baz` 的值 */,
oldValue: /* 上一次更新时 `baz` 的值 */
}
传参动态写法
<div v-example:[arg]="value"></div>
app.use()
js
import { createApp } from 'vue'
import MyPlugin from './plugins/MyPlugin'
const app = createApp({})
app.use(MyPlugin)
// MyPlugin 插件
export default {
install: (app, options) => {
// 注入一个全局可用的 $translate() 方法
app.config.globalProperties.$translate = (key) => {
// 获取 `options` 对象的深层属性
// 使用 `key` 作为索引
return key.split('.').reduce((o, i) => {
if (o) return o[i]
}, options)
}
}
}
// 可使用
<h1>{{ $translate('greetings.hello') }}</h1>
app.mixin()
js
// Mixins 在 Vue 3 支持主要是为了向后兼容,若要进行逻辑复用,推荐用组合式函数来替代。
// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'
// 按照惯例,组合式函数名以"use"开头
export function useMouse() {
// 被组合式函数封装和管理的状态
const x = ref(0)
const y = ref(0)
// 组合式函数可以随时更改其状态。
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
// 一个组合式函数也可以挂靠在所属组件的生命周期上
// 来启动和卸载副作用
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
// 通过返回值暴露所管理的状态
return { x, y }
}
// 使用案例
<template>Mouse position is at: {{ x }}, {{ y }}</template>
<script setup>
import { useMouse } from './mouse.js'
const { x, y } = useMouse()
</script>
app.provide()
js
import { createApp } from 'vue'
const app = createApp()
app.provide('message', 'hello')
import { inject } from 'vue'
export default {
setup() {
console.log(inject('message')) // 'hello'
}
}
app.runWithContext() 使用当前应用作为注入上下文执行回调函数。
js
import { inject } from 'vue'
app.provide('id', 1)
const injected = app.runWithContext(() => {
return inject('id')
})
console.log(injected) // 1
app.version
js
export default {
install(app) {
console.log( app.version )
}
}
app.config
js
// 可以在挂载应用前更改这些属性
import { createApp } from 'vue'
const app = createApp(/* ... */)
console.log(app.config)
app.config.errorHandler
app.config.warnHandler
app.config.performance
app.config.compilerOptions
app.config.globalProperties
js
app.config.globalProperties.msg = 'hello'
app.config.optionMergeStrategies
js
const app = createApp({
// 自身的选项
msg: 'Vue',
// 来自 mixin 的选项
mixins: [
{
msg: 'Hello '
}
],
mounted() {
// 在 this.$options 上暴露被合并的选项
console.log(this.$options.msg)
}
})
// 为 `msg` 定义一个合并策略函数
app.config.optionMergeStrategies.msg = (parent, child) => {
return (parent || '') + (child || '')
}
app.mount('#app')// 打印 'Hello Vue'
version
js
import { version } from 'vue'
console.log(version)
nextTick()
js
// 等待下一次 DOM 更新刷新的工具方法。
function nextTick(callback?: () => void): Promise<void>
nextTick() 可以在状态改变后立即使用,以等待 DOM 更新完成。你可以传递一个回调函数作为参数,或者 await 返回的 Promise。
<template>
<button id="counter" @click="increment">{{ count }}</button>
</template>
<script setup>
import { ref, nextTick } from 'vue'
const count = ref(0)
async function increment() {
count.value++
// DOM 还未更新
console.log(document.getElementById('counter').textContent) // 0
await nextTick()
// DOM 此时已经更新
console.log(document.getElementById('counter').textContent) // 1
}
</script>
defineComponent()
js
import { ref, h } from 'vue'
const Comp = defineComponent(
(props) => {
// 就像在 <script setup> 中一样使用组合式 API
const count = ref(0)
return () => {
// 渲染函数或 JSX
return h('div', count.value)
}
},
// 其他选项,例如声明 props 和 emits。
{
props: {
/* ... */
}
}
)
因为 defineComponent() 是一个函数调用,
所以它可能被某些构建工具认为会产生副作用,如 webpack。
即使一个组件从未被使用,也有可能不被 tree-shake。
为了告诉 webpack 这个函数调用可以被安全地 tree-shake,
我们可以在函数调用之前添加一个 /*#__PURE__*/ 形式的注释:
export default /*#__PURE__*/ defineComponent(/* ... */)
defineAsyncComponent()
defineCustomElement()
Setup 基本使用
html
<template>
<button @click="count++">{{ count }}</button>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
// 返回值会暴露给模板和其他的选项式 API 钩子
return {
count // 它会自动浅层解包,因此你无须再在模板中为它写 .value
}
},
mounted() {
console.log(this.count) // 通过 this 访问时也会同样如此解包。
}
}
</script>
访问 Props
js
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
import { toRefs, toRef } from 'vue'
export default {
setup(props) {
// 将 `props` 转为一个其中全是 ref 的对象,然后解构
const { title } = toRefs(props)
// `title` 是一个追踪着 `props.title` 的 ref
console.log(title.value)
// 或者,将 `props` 的单个属性转为一个 ref
const title = toRef(props, 'title')
}
}
Setup 上下文
js
export default {
setup(props, { attrs, slots, emit, expose }) {
console.log(attrs)// 透传 Attributes(非响应式的对象,等价于 $attrs)
console.log(slots)// 插槽(非响应式的对象,等价于 $slots)
console.log(emit)// 触发事件(函数,等价于 $emit
console.log(expose)// 暴露公共属性(函数)
// attrs, slots 是有状态的,但是他的属性没有状态,
// 如果你想要基于 attrs 或 slots 的改变来执行副作用,
// 那么你应该在 onBeforeUpdate 生命周期钩子中编写相关逻辑。
}
}
// 暴露公共属性
// expose 函数用于显式地限制该组件暴露出的属性,当父组件通过模板引用访问该组件的实例时,
// 将仅能访问 expose 函数暴露出的内容:
export default {
setup(props, { expose }) {
// 让组件实例处于 "关闭状态"
// 即不向父组件暴露任何东西
expose()
const publicCount = ref(0)
const privateCount = ref(0)
// 有选择地暴露局部状态
expose({ count: publicCount })
}
}
与渲染函数一起使用
js
import { h, ref } from 'vue'
export default {
setup(props, { expose }) {
const count = ref(0)
const increment = () => ++count.value
expose({ increment})
return () => h('div', count.value)
}
}
ref()
js
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
computed()
js
// 创建一个只读的计算属性 ref:
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 错误
reactive()
readonly()
watchEffect()
watchPostEffect()
watchSyncEffect()
watch()