vue3的api使用

news/2025/2/11 1:41:50/

vue官网链接
API 全览图

createApp()

// 内敛根组建
import { createApp } from 'vue'
const app = createApp({})// 导入根组建
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)

app.mount()

import { createApp } from 'vue'
const app = createApp(/* ... */)
const vm = app.mount('#app')
vm.unmount() // 在需要卸载应用时,调用

app.unmount() 可以卸载局部组件,而不影响整个应用,下面是手动卸载

import { defineComponent } from 'vue'
export default defineComponent({methods:{handleUnmount(){this.$el.parentElement.removeChild(this.$el)this.$destroy()}}
})

app.component()

import { createApp } from 'vue'
const app = createApp({})
// 得到一个已注册的组件
const MyComponent = app.component('my-component')

app.directive()

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-focusfocus: {}}
}全局注册
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()

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()

// 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.pageXy.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()

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() 使用当前应用作为注入上下文执行回调函数。

import { inject } from 'vue'
app.provide('id', 1)
const injected = app.runWithContext(() => {return inject('id')
})
console.log(injected) // 1

app.version

export default {install(app) {console.log( app.version )}
}

app.config

// 可以在挂载应用前更改这些属性
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

app.config.globalProperties.msg = 'hello'

app.config.optionMergeStrategies

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

import { version } from 'vue'
console.log(version)

nextTick()

// 等待下一次 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) // 0await nextTick()// DOM 此时已经更新console.log(document.getElementById('counter').textContent) // 1
}
</script>

defineComponent()

import { ref, h } from 'vue'const Comp = defineComponent((props) => {// 就像在 <script setup> 中一样使用组合式 APIconst count = ref(0)return () => {// 渲染函数或 JSXreturn h('div', count.value)}},// 其他选项,例如声明 props 和 emits。{props: {/* ... */}}
)因为 defineComponent() 是一个函数调用,
所以它可能被某些构建工具认为会产生副作用,如 webpack。
即使一个组件从未被使用,也有可能不被 tree-shake。
为了告诉 webpack 这个函数调用可以被安全地 tree-shake,
我们可以在函数调用之前添加一个 /*#__PURE__*/ 形式的注释:
export default /*#__PURE__*/ defineComponent(/* ... */)

defineAsyncComponent()
defineCustomElement()
Setup 基本使用

<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

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` 的 refconsole.log(title.value)// 或者,将 `props` 的单个属性转为一个 refconst title = toRef(props, 'title')}
}

Setup 上下文

export default {setup(props, { attrs, slots, emit, expose }) {console.log(attrs)// 透传 Attributes(非响应式的对象,等价于 $attrs)console.log(slots)// 插槽(非响应式的对象,等价于 $slots)console.log(emit)// 触发事件(函数,等价于 $emitconsole.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 })}
}

与渲染函数一起使用

import { h, ref } from 'vue'
export default {setup(props, { expose }) {const count = ref(0)const increment = () => ++count.valueexpose({ increment})return () => h('div', count.value)}
}

ref()

const count = ref(0)
console.log(count.value) // 0count.value++
console.log(count.value) // 1

computed()

// 创建一个只读的计算属性 ref:
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 错误

reactive()

const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 错误

readonly()

const original = reactive({ count: 0 })
const copy = readonly(original)
watchEffect(() => {// 用来做响应性追踪console.log(copy.count)
})// 更改源属性会触发其依赖的侦听器
original.count++// 更改该只读副本将会失败,并会得到一个警告
copy.count++ // warning!

watch()

const todoId = ref(1)
const data = ref(null)// watch只追踪明确侦听的数据源
watch(todoId, async () => {const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${todoId.value}`)data.value = await response.json()
}, { immediate: true })// 上述简化,watchEffect() 允许我们自动跟踪回调的响应式依赖。
// 缺点是:响应性依赖关系会不那么明确
// watchEffect 仅会在其同步执行期间,才追踪依赖。
// 在使用异步回调时,只有在第一个 await 正常工作前访问到的属性才会被追踪。
watchEffect(async () => {const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${todoId.value}`)data.value = await response.json()
})

watchEffect()

const count = ref(0)
watchEffect(() => console.log(count.value)) // -> 输出 0
count.value++ // -> 输出 1// 副作用清除:
watchEffect(async (onCleanup) => {const { response, cancel } = doAsyncWork(id.value)// `cancel` 会在 `id` 更改时调用//  以便取消之前 , 未完成的请求onCleanup(cancel)data.value = await response
})// 停止侦听器:
const stop = watchEffect(() => {})
// 当不再需要此侦听器时:
stop()// 侦听器必须用同步语句创建:如果用异步回调创建一个侦听器,
// 那么它不会绑定到当前组件上,你必须手动停止它,以防内存泄漏
watchEffect(() => {}) // 它会自动停止setTimeout(() => { watchEffect(() => {}) // ...这个则不会!
}, 100)

watchPostEffect()

// 默认情况下,用户创建的侦听器回调,都会在 Vue 组件更新之前被调用。
// 这意味着你在侦听器回调中访问的 DOM 将是被 Vue 更新之前的状态。
// 如果想在侦听器回调中能访问被 Vue 更新之后的 DOM,你需要指明 flush: 'post' 选项:
watch(source, callback, {flush: 'post'
})
watchEffect(callback, {flush: 'post'
})// 简写的方式有
import { watchPostEffect } from 'vue'
watchPostEffect(() => {/* 在 Vue 更新后执行 */
})

watchSyncEffect()

// 默认情况下,侦听器将在组件渲染之前执行。
// 设置 flush: 'post' 将会使侦听器延迟到组件渲染之后再执行
// 在某些特殊情况下 (例如要使缓存失效),可能有必要在响应式依赖发生改变时立即触发侦听器。
// 这可以通过设置 flush: 'sync' 来实现。
// 然而,该设置应谨慎使用,因为如果有多个属性同时更新,这将导致一些性能和数据一致性的问题。
watch(source, callback, {flush: 'pre | post | sync' // 默认值:pre
})watchSyncEffect 是 上面参数为sync的简写

isRef()

// 检查某个值是否为 ref。
let foo: unknown
if (isRef(foo)) {foo.value
}

unref()

// 如果参数是 ref,则返回内部值,否则返回参数本身。
// 这是 val = isRef(val) ? val.value : val 计算的一个语法糖。
function useFoo(x: number | Ref<number>) {const unwrapped = unref(x)// unwrapped 现在保证为 number 类型
}

toRef()

// 按原样返回现有的 ref
toRef(existingRef)// 创建一个只读的 ref,当访问 .value 时会调用此 getter 函数
toRef(() => props.foo)// 从非函数的值中创建普通的 ref
// 等同于 ref(1)
toRef(1)

toValue()

// 将值、refs 或 getters 规范化为值。这与 unref() 类似,不同的是此函数也会规范化 getter 函数。
// 如果参数是一个 getter,它将会被调用并且返回它的返回值。
toValue(1) //       --> 1
toValue(ref(1)) //  --> 1
toValue(() => 1) // --> 1

toRefs()

// 将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。
// 每个单独的 ref 都是使用 toRef() 创建的。
function useFeatureX() {const state = reactive({foo: 1,bar: 2})// ...基于状态的操作逻辑// 在返回时都转为 refreturn toRefs(state)
}
// 可以解构而不会失去响应性
const { foo, bar } = useFeatureX()

isProxy()

// 检查一个对象是否是由 reactive()、readonly()、
// shallowReactive() 或 shallowReadonly() 创建的代理。
function isProxy(value: unknown): boolean

isReactive()

// 检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。
function isReactive(value: unknown): boolean

isReadonly()

// 检查传入的值是否为只读对象。只读对象的属性可以更改,但他们不能通过传入的对象直接赋值。
// 通过 readonly() 和 shallowReadonly() 创建的代理都是只读的,
// 因为他们是没有 set 函数的 computed() ref。
function isReadonly(value: unknown): boolean

shallowRef()

/**
和 ref() 不同,浅层 ref 的内部值将会原样存储和暴露,并且不会被深层递归地转为响应式。
只有对 .value 的访问是响应式的。
shallowRef() 常常用于对大型数据结构的性能优化或是与外部的状态管理系统集成。
*/
const state = shallowRef({ count: 1 })
state.value.count = 2 // 不会触发更改
state.value = { count: 2 } // 会触发更改

triggerRef()

/**
强制触发依赖于一个浅层 ref 的副作用,这通常在对浅引用的内部值进行深度变更后使用。
*/
const shallow = shallowRef({greet: 'Hello, world'
})// 触发该副作用第一次应该会打印 "Hello, world"
watchEffect(() => {console.log(shallow.value.greet)
})// 这次变更不应触发副作用,因为这个 ref 是浅层的
shallow.value.greet = 'Hello, universe'// 打印 "Hello, universe"
triggerRef(shallow)

customRef()

/**
创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式。
*/
import { customRef } from 'vue'
export function useDebouncedRef(value, delay = 200) {let timeoutreturn customRef((track, trigger) => {return {get() {track() // 取了,就跟踪return value},set(newValue) {clearTimeout(timeout)timeout = setTimeout(() => {value = newValue // 设置新值后,延迟更新。trigger()}, delay)}}})
}

shallowReactive()

/**
和 reactive() 不同,这里没有深层级的转换:一个浅层响应式对象里只有根级别的属性是响应式的。
属性的值会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。
*/
const state = shallowReactive({foo: 1,nested: {bar: 2}
})// 更改状态自身的属性是响应式的
state.foo++// 下层嵌套对象不会被转为响应式
isReactive(state.nested) // false
state.nested.bar++ // 不是响应式的

shallowReadonly()

/**
readonly() 的浅层作用形式
和 readonly() 不同,这里没有深层级的转换:只有根层级的属性变为了只读。
属性的值都会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。
*/
const state = shallowReadonly({foo: 1,nested: {bar: 2}
})
state.foo++ // 更改状态自身的属性会失败
// ...但可以更改下层嵌套对象
isReadonly(state.nested) // false
state.nested.bar++ // 这是可以通过的

toRaw()

/**
根据一个 Vue 创建的代理返回其原始对象。
toRaw() 可以返回由 reactive()、readonly()、shallowReactive() 
或者 shallowReadonly() 创建的代理对应的原始对象。
这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。
不建议保存对原始对象的持久引用,请谨慎使用。
*/
const foo = {}
const reactiveFoo = reactive(foo)
console.log(toRaw(reactiveFoo) === foo) // true

markRaw()

/**
将一个对象标记为不可被转为代理。返回该对象本身。
*/
const foo = markRaw({})
console.log(isReactive(reactive(foo))) // false// 也适用于嵌套在其他响应性对象
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false

effectScope()

/**
创建一个 effect 作用域,可以捕获其中所创建的响应式副作用 (即计算属性和侦听器),这样捕获到的副作用可以一起处理。对于该 API 的使用细节,请查阅对应的 RFC。
*/
const scope = effectScope()scope.run(() => {const doubled = computed(() => counter.value * 2)watch(doubled, () => console.log(doubled.value))watchEffect(() => console.log('Count: ', doubled.value))
})// 处理掉当前作用域内的所有 effect
scope.stop()

getCurrentScope()

/**
如果有的话,返回当前活跃的 effect 作用域。
*/
function getCurrentScope(): EffectScope | undefined

onScopeDispose()

/**
在当前活跃的 effect 作用域上注册一个处理回调函数。
当相关的 effect 作用域停止时会调用这个回调函数。
这个方法可以作为可复用的组合式函数中 onUnmounted 的替代品,它并不与组件耦合,
因为每一个 Vue 组件的 setup() 函数也是在一个 effect 作用域中调用的。
*/
function onScopeDispose(fn: () => void): void

onMounted()

/**
组件在以下情况下被视为已挂载:
其所有同步子组件都已经被挂载 (不包含异步组件或 <Suspense> 树内的组件)。其自身的 DOM 树已经创建完成并插入了父容器中。注意仅当根容器在文档中时,
才可以保证组件 DOM 树也在文档中。这个钩子通常用于执行需要访问组件所渲染的 DOM 树相关的副作用,
或是在服务端渲染应用中用于确保 DOM 相关代码仅在客户端执行。这个钩子在服务器端渲染期间不会被调用。
*/
<template><div ref="el"></div>
</template>
<script setup>import { ref, onMounted } from 'vue'const el = ref()onMounted(() => {el.value // <div>})
</script>

onUpdated()

/**
父组件的更新钩子将在其子组件的更新钩子之后调用。这个钩子会在组件的任意 DOM 更新后被调用,这些更新可能是由不同的状态变更导致的,
因为多个状态变更可以在同一个渲染周期中批量执行(考虑到性能因素)。
如果你需要在某个特定的状态更改后访问更新后的 DOM,请使用 nextTick() 作为替代。这个钩子在服务器端渲染期间不会被调用。
*/
<template><button id="count" @click="count++">{{ count }}</button>
</template>
<script setup>import { ref, onUpdated } from 'vue'const count = ref(0)onUpdated(() => {// 文本内容应该与当前的 `count.value` 一致console.log(document.getElementById('count').textContent)})
</script>

onUnmounted()

/**
注册一个回调函数,在组件实例被卸载之后调用。
一个组件在以下情况下被视为已卸载:
其所有子组件都已经被卸载。
所有相关的响应式作用 (渲染作用以及 setup() 时创建的计算属性和侦听器) 都已经停止。
可以在这个钩子中手动清理一些副作用,例如计时器、DOM 事件监听器或者与服务器的连接。
这个钩子在服务器端渲染期间不会被调用。
*/
<script setup>
import { onMounted, onUnmounted } from 'vue'
let intervalId
onMounted(() => {intervalId = setInterval( () => { } )
})
onUnmounted(() => clearInterval(intervalId))
</script>

onBeforeMount()

/**
注册一个钩子,在组件被挂载之前被调用。
当这个钩子被调用时,组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。它即将首次执行 DOM 渲染过程。这个钩子在服务器端渲染期间不会被调用。
*/

onBeforeUpdate()

/**
注册一个钩子,在组件即将因为响应式状态变更而更新其 DOM 树之前调用。
这个钩子可以用来在 Vue 更新 DOM 之前访问 DOM 状态。在这个钩子中更改状态也是安全的。这个钩子在服务器端渲染期间不会被调用。
*/

onBeforeUnmount()

/**
注册一个钩子,在组件实例被卸载之前调用。
当这个钩子被调用时,组件实例依然还保有全部的功能。
这个钩子在服务器端渲染期间不会被调用。
*/

onErrorCaptured()

/**
注册一个钩子,在捕获了后代组件传递的错误时调用。
错误可以从以下几个来源中捕获:组件渲染事件处理器生命周期钩子setup() 函数侦听器自定义指令钩子过渡钩子
*/

onRenderTracked()

/**
注册一个调试钩子,当组件渲染过程中追踪到响应式依赖时调用。这个钩子仅在开发模式下可用,且在服务器端渲染期间不会被调用。
*/

onRenderTriggered()

/**
注册一个调试钩子,当响应式依赖的变更触发了组件渲染时调用。这个钩子仅在开发模式下可用,且在服务器端渲染期间不会被调用。
*/

onActivated()

/**
注册一个回调函数,若组件实例是 <KeepAlive> 缓存树的一部分,当组件被插入到 DOM 中时调用。这个钩子在服务器端渲染期间不会被调用。
*/

onDeactivated()

/**
注册一个回调函数,若组件实例是 <KeepAlive> 缓存树的一部分,当组件从 DOM 中被移除时调用。这个钩子在服务器端渲染期间不会被调用。
*/

onServerPrefetch()

/**
注册一个异步函数,在组件实例在服务器上被渲染之前调用。如果这个钩子返回了一个 Promise,服务端渲染会在渲染该组件前等待该 Promise 完成。这个钩子仅会在服务端渲染中执行,可以用于执行一些仅存在于服务端的数据抓取过程。
*/
<script setup>
import { ref, onServerPrefetch, onMounted } from 'vue'
const data = ref(null)
onServerPrefetch(async () => {// 组件作为初始请求的一部分被渲染// 在服务器上预抓取数据,因为它比在客户端上更快。data.value = await fetchOnServer(/* ... */)
})
onMounted(async () => {if (!data.value) {// 如果数据在挂载时为空值,这意味着该组件// 是在客户端动态渲染的。将转而执行// 另一个客户端侧的抓取请求data.value = await fetchOnClient(/* ... */)}
})
</script>

provide()

/**
提供一个值,可以被后代组件注入。
provide() 接受两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,
第二个参数是要注入的值。当使用 TypeScript 时,key 可以是一个被类型断言为 InjectionKey 的 symbol。
InjectionKey 是一个 Vue 提供的工具类型,继承自 Symbol,
可以用来同步 provide() 和 inject() 之间值的类型。与注册生命周期钩子的 API 类似,provide() 必须在组件的 setup() 阶段同步调用。*/
<script setup>
import { ref, provide } from 'vue'
import { fooSymbol } from './injectionSymbols'// 提供静态值
provide('foo', 'bar')// 提供响应式的值
const count = ref(0)
provide('count', count)// 提供时将 Symbol 作为 key
provide(fooSymbol, count)
</script>

inject()

/**
注入一个由祖先组件或整个应用 (通过 app.provide()) 提供的值。
第一个参数是注入的 key。Vue 会遍历父组件链,通过匹配 key 来确定所提供的值。如果父组件链上多个组件对同一个 key 提供了值,那么离得更近的组件将会“覆盖”链上更远的组件所提供的值。如果没有能通过 key 匹配到值,inject() 将返回 undefined,除非提供了一个默认值。第二个参数是可选的,即在没有匹配到 key 时使用的默认值。第二个参数也可以是一个工厂函数,用来返回某些创建起来比较复杂的值。在这种情况下,你必须将 true 作为第三个参数传入,表明这个函数将作为工厂函数使用,而非值本身。与注册生命周期钩子的 API 类似,inject() 必须在组件的 setup() 阶段同步调用。当使用 TypeScript 时,key 可以是一个类型为 InjectionKey 的 symbol。InjectionKey 是一个 Vue 提供的工具类型,继承自 Symbol,可以用来同步 provide() 和 inject() 之间值的类型。*/
<script setup>
import { inject } from 'vue'
import { fooSymbol } from './injectionSymbols'// 注入不含默认值的静态值
const foo = inject('foo')// 注入响应式的值
const count = inject('count')// 通过 Symbol 类型的 key 注入
const foo2 = inject(fooSymbol)// 注入一个值,若为空则使用提供的默认值
const bar = inject('foo', 'default value')// 注入一个值,若为空则使用提供的函数类型的默认值
const fn = inject('function', () => {})// 注入一个值,若为空则使用提供的工厂函数
const baz = inject('factory', () => new ExpensiveObject(), true)
</script>

data

/**
如果一个属性的值在一开始还获取不到,应当先用 undefined 或是 null 值来占位,
让 Vue 知道这个属性是存在的。以 _ 或 $ 开头的属性将不会被组件实例代理,因为它们可能和 Vue 的内置属性、API 方法冲突。
你必须以 this.$data._property 的方式访问它们。
*/
export default {data() {return { a: 1 }},created() {console.log(this.a) // 1console.log(this.$data) // { a: 1 }}
}

props

/**
type:可以是下列原生构造函数之一:String、Number、Boolean、Array、Object、Date、Function、Symbol、任何自定义构造函数,或由上述内容组成的数组。在开发模式中,Vue 会检查一个 prop 的值是否匹配其声明的类型,如果不匹配则会抛出警告。详见 Prop 校验。还要注意,一个 Boolean 类型的 prop 会影响它在开发或生产模式下的值转换行为。详见 Boolean 类型转换。default:为该 prop 指定一个当其没有被传入或值为 undefined 时的默认值。对象或数组的默认值必须从一个工厂函数返回。工厂函数也接收原始 prop 对象作为参数。required:定义该 prop 是否必需传入。在非生产环境中,如果 required 值为真值且 prop 未被传入,一个控制台警告将会被抛出。validator:将 prop 值作为唯一参数传入的自定义验证函数。在开发模式下,如果该函数返回一个假值 (即验证失败),一个控制台警告将会被抛出。
*/
export default {props: {// 类型检查height: Number,// 类型检查 + 其他验证age: {type: Number,default: 0,required: true,validator: (value) => {return value >= 0}}}
}

computed

/**
用于声明要在组件实例上暴露的计算属性。
该选项接收一个对象,其中键是计算属性的名称,值是一个计算属性 getter,
或一个具有 get 和 set 方法的对象 (用于声明可写的计算属性)。所有的 getters 和 setters 会将它们的 this 上下文自动绑定为组件实例。注意,如果你为一个计算属性使用了箭头函数,则 this 不会指向该组件实例,
不过你仍然可以通过该函数的第一个参数来访问实例:
*/
export default {data() {return { a: 1 }},computed: {// 只读aDouble() {return this.a * 2},// 可写aPlus: {get() {return this.a + 1},set(v) {this.a = v - 1}}},created() {console.log(this.aDouble) // => 2console.log(this.aPlus) // => 2this.aPlus = 3console.log(this.a) // => 2console.log(this.aDouble) // => 4}
}

methods

/**
声明的方法可以直接通过组件实例访问,或者在模板语法表达式中使用。
所有的方法都会将它们的 this 上下文自动绑定为组件实例,即使在传递时也如此。在声明方法时避免使用箭头函数,因为它们不能通过 this 访问组件实例。
*/
export default {data() {return { a: 1 }},methods: {plus() {this.a++}},created() {this.plus()console.log(this.a) // => 2}
}

watch

/**
用于声明在数据更改时调用的侦听回调。
watch 选项期望接受一个对象,其中键是需要侦听的响应式组件实例属性 (例如,通过 data 或 computed 声明的属性)——值是相应的回调函数。该回调函数接受被侦听源的新值和旧值。除了一个根级属性,键名也可以是一个简单的由点分隔的路径,例如 a.b.c。注意,这种用法不支持复杂表达式——仅支持由点分隔的路径。如果你需要侦听复杂的数据源,可以使用命令式的 $watch() API。值也可以是一个方法名称的字符串 (通过 methods 声明),或包含额外选项的对象。当使用对象语法时,回调函数应被声明在 handler 中。额外的选项包含:immediate:在侦听器创建时立即触发回调。第一次调用时,旧值将为 undefined。
deep:如果源是对象或数组,则强制深度遍历源,以便在深度变更时触发回调。详见深层侦听器。
flush:调整回调的刷新时机。详见回调的触发时机及 watchEffect()。
onTrack / onTrigger:调试侦听器的依赖关系。详见侦听器调试。
声明侦听器回调时避免使用箭头函数,因为它们将无法通过 this 访问组件实例。
*/
export default {data() {return {a: 1,b: 2,c: {d: 4},e: 5,f: 6}},watch: {// 侦听根级属性a(val, oldVal) {console.log(`new: ${val}, old: ${oldVal}`)},// 字符串方法名称b: 'someMethod',// 该回调将会在被侦听的对象的属性改变时调动,无论其被嵌套多深c: {handler(val, oldVal) {console.log('c changed')},deep: true},// 侦听单个嵌套属性:'c.d': function (val, oldVal) {// do something},// 该回调将会在侦听开始之后立即调用e: {handler(val, oldVal) {console.log('e changed')},immediate: true},// 你可以传入回调数组,它们将会被逐一调用f: ['handle1',function handle2(val, oldVal) {console.log('handle2 triggered')},{handler: function handle3(val, oldVal) {console.log('handle3 triggered')}/* ... */}]},methods: {someMethod() {console.log('b changed')},handle1() {console.log('handle 1 triggered')}},created() {this.a = 3 // => new: 3, old: 1}
}

emits

/**
用于声明由组件触发的自定义事件。
可以以两种形式声明触发的事件:使用字符串数组的简易形式。
使用对象的完整形式。该对象的每个属性键是事件的名称,值是 null 或一个验证函数。
验证函数会接收到传递给组件的 $emit 调用的额外参数。例如,如果 this.$emit('foo', 1) 被调用,foo 相应的验证函数将接受参数 1。验证函数应返回布尔值,以表明事件参数是否通过了验证。注意,emits 选项会影响一个监听器被解析为组件事件监听器,还是原生 DOM 事件监听器。被声明为组件事件的监听器不会被透传到组件的根元素上,且将从组件的 $attrs 对象中移除。
*/
// 数组语法:
export default {emits: ['check'],created() {this.$emit('check')}
}// 对象语法:
export default {emits: {// 没有验证函数click: null,// 具有验证函数submit: (payload) => {if (payload.email && payload.password) {return true} else {console.warn(`Invalid submit event payload!`)return false}}}
}

expose

/**
用于声明当组件实例被父组件通过模板引用访问时暴露的公共属性。
默认情况下,当通过 $parent、$root 或模板引用访问时,组件实例将向父组件暴露所有的实例属性。这可能不是我们希望看到的,因为组件很可能拥有一些应保持私有的内部状态或方法,以避免紧耦合。expose 选项值应当是一个包含要暴露的属性名称字符串的数组。当使用 expose 时,只有显式列出的属性将在组件实例上暴露。expose 仅影响用户定义的属性——它不会过滤掉内置的组件实例属性。
*/
export default {// 只有 `publicMethod` 在公共实例上可用expose: ['publicMethod'],methods: {publicMethod() {// ...},privateMethod() {// ...}}
}

template

/**
通过 template 选项提供的模板将会在运行时即时编译。这仅在使用了包含模板编译器的 Vue 构建版本的情况下支持。文件名中带有 runtime 的 Vue 构建版本未包含模板编译器,例如 vue.runtime.esm-bundler.js。请查阅构建文件指南了解不同构建版本之间的详细区别。如果该字符串以 # 开头,它将被用作 querySelector 的选择器,并使用所选中元素的 innerHTML 作为模板字符串。这让我们能够使用原生 <template> 元素来书写源模板。如果 render 选项也同时存在于该组件中,template 将被忽略。如果应用的根组件不含任何 template 或 render 选项,Vue 将会尝试使用所挂载元素的 innerHTML 来作为模板。
*/

render

/**
用于编程式地创建组件虚拟 DOM 树的函数。
render 是字符串模板的一种替代,可以使你利用 JavaScript 的丰富表达力来完全编程式地声明组件最终的渲染输出。预编译的模板,例如单文件组件中的模板,会在构建时被编译为 render 选项。如果一个组件中同时存在 render 和 template,则 render 将具有更高的优先级。
*/

compilerOptions

/**
用于配置组件模板的运行时编译器选项。
这个配置选项仅在使用完整构建版本 (即可以在浏览器中编译模板的 vue.js 文件) 时才有效。
它支持与应用级的 app.config.compilerOptions 相同的选项,并针对当前组件有更高的优先级。
*/

slots

/**
一个在渲染函数中以编程方式使用插槽时辅助类型推断的选项。仅在 Vue 3.3+ 中支持。
该选项的运行时值不会被使用。实际类型应通过 SlotsType 类型辅助工具进行类型转换来声明:
*/
import { SlotsType } from 'vue'defineComponent({slots: Object as SlotsType<{default: { foo: string; bar: number }item: { data: number }}>,setup(props, { slots }) {expectType<undefined | ((scope: { foo: string; bar: number }) => any)>(slots.default)expectType<undefined | ((scope: { data: number }) => any)>(slots.item)}
})

beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeUnmount
unmounted
errorCaptured
renderTracked
renderTriggered
activated
deactivated
serverPrefetch
provide
inject
mixins
extends
name
inheritAttrs
components
directives
$data
$props
$el
$options
$parent
$root
$slots
$refs
$attrs
$watch()
$emit()
$forceUpdate()
$nextTick()
v-text
v-html
v-show
v-if
v-else
v-else-if
v-for
v-on
v-bind
v-model
v-slot
v-pre
v-once
v-memo
v-cloak








key
ref
is
组件作用域 CSS

/** 
当 <style> 标签带有 scoped attribute 的时候,它的 CSS 只会影响当前组件的元素,
和 Shadow DOM 中的样式封装类似。使用时有一些注意事项,不过好处是不需要任何的 polyfill。
它的实现方式是通过 PostCSS 将以下内容:
*/<style scoped>.example {color: red;}
</style><template><div class="example">hi</div>
</template>
// 转换为:
<style>.example[data-v-f3f3eg9] {color: red;}
</style><template><div class="example" data-v-f3f3eg9>hi</div>
</template>
子组件的根元素​
使用 scoped 后,父组件的样式将不会渗透到子组件中。
不过,子组件的根节点会同时被父组件的作用域样式和子组件的作用域样式影响。
这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。深度选择器​
处于 scoped 样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用 :deep() 这个伪类:
<style scoped>
.a :deep(.b) {/* ... */
}
</style>
上面的代码会被编译成:
.a[data-v-f3f3eg9] .b {/* ... */
}

CSS Modules

/**
一个 <style module> 标签会被编译为 CSS Modules 并且将生成的 CSS class 作为 $style 对象暴露给组件:
得出的 class 将被哈希化以避免冲突,实现了同样的将 CSS 仅作用于当前组件的效果。
*/
<template><p :class="$style.red">This should be red</p>
</template>
<style module>
.red {color: red;
}
</style>// 你可以通过给 module attribute 一个值来自定义注入 class 对象的属性名:
<template><p :class="classes.red">red</p>
</template>
<style module="classes">
.red {color: red;
}
</style>

CSS 中的 v-bind()

/**
单文件组件的 <style> 标签支持使用 v-bind CSS 函数将 CSS 的值链接到动态的组件状态:
*/
<template><div class="text">hello</div>
</template><script>
export default {data() {return {color: 'red'}}
}
</script><style>
.text {color: v-bind(color);
}
</style>
/**
这个语法同样也适用于 <script setup>,且支持 JavaScript 表达式 (需要用引号包裹起来):
实际的值会被编译成哈希化的 CSS 自定义属性,因此 CSS 本身仍然是静态的。
自定义属性会通过内联样式的方式应用到组件的根元素上,并且在源值变更的时候响应式地更新。
*/
<script setup>const theme = {color: 'red'}
</script><template><p>hello</p>
</template><style scoped>
p {color: v-bind('theme.color');
}
</style>

基本语法

<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。
当同时使用 SFC 与组合式 API 时该语法是默认推荐。相比于普通的 <script> 语法,
它具有更多优势:
更少的样板内容,更简洁的代码。
能够使用纯 TypeScript 声明 props 和自定义事件。
更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)。
更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)/**
当使用 <script setup> 的时候,任何在 <script setup> 声明的顶层的绑定 (包括变量,函数声明,以及 import 导入的内容) 都能在模板中直接使用:
*/
<template><button @click="log">{{ msg }}</button><div>{{ capitalize('hello') }}</div><button @click="count++">{{ count }}</button><MyComponent /><component :is="Foo" /><component :is="someCondition ? Foo : Bar" /><Form.Input><Form.Label>label</Form.Label></Form.Input>
</template>
<script setup>import { capitalize } from './helpers'import { ref } from 'vue'import MyComponent from './MyComponent.vue'import Foo from './Foo.vue'import Bar from './Bar.vue'import { FooBar as FooBarChild } from './components' // 换名import * as Form from './form-components'import { useSlots, useAttrs } from 'vue'const msg = 'Hello!' // 变量function log() { // 函数console.log(msg)}const count = ref(0)// 为了在声明 props 和 emits 选项时获得完整的类型推导支持,// 我们可以使用 defineProps 和 defineEmits API,// 它们将自动地在 <script setup> 中可用:// defineProps,defineEmits不需导入,会随着 <script setup> 的处理过程一同被编译掉const props = defineProps({ foo: String })	// 使用 props.foo const emit = defineEmits(['change', 'delete']) // 使用 emit('change',{k:1}) defineExpose({ a, b }) // 暴露给父组件的属性defineOptions({ name:'F' })// 跟export default 导出属性类似// useSlots 和 useAttrs 是真实的运行时函数,// 它的返回与 setupContext.slots 和 setupContext.attrs 等价。。const slots = useSlots()const attrs = useAttrs()
</script>

defineSlots()

// 需要在ts环境用
<script setup lang="ts">
const slots = defineSlots<{default(props: { msg: string }): any
}>()
</script>

http://www.ppmy.cn/news/1229769.html

相关文章

2分钟快速安装 `nginx` 和配置 `keepalived`

这是详细的步骤来在 CentOS 7 上安装 nginx 和配置 keepalived。 主服务器&#xff08;IP: 192.168.9.195&#xff09; 安装 Nginx 安装 EPEL 仓库&#xff1a; sudo yum install epel-release -y安装 Nginx&#xff1a; sudo yum install nginx -y启动 Nginx 服务并设置开机…

ACWSpring1.3

git使用git status看我们仓库有多少什么东西 首先,前端写ajax写上我们的访问路径(就在我们前端的源代码里面),我们建了两个包pkController用于前端页面url映射过来一层一层找到我们的RestController返回bot1里面有键值,返回的这就是一个session对象bot1这个map.前端拿到我们bot…

tcpdump使用方法

目录 安装 tcpdump 使用基本命令 示例 1. 捕获所有流量 2. 指定网络接口 3. 保存到文件 4. 显示包的详细信息 5. 过滤特定主机 6. 过滤特定端口 7. 组合过滤条件 更多选项和过滤表达式 tcpdump 是一个用于在命令行中进行网络抓包的工具&#xff0c;它允许你捕获和分…

Javaweb之Ajax的详细解析

1.1 Ajax介绍 1.1.1 Ajax概述 我们前端页面中的数据&#xff0c;如下图所示的表格中的学生信息&#xff0c;应该来自于后台&#xff0c;那么我们的后台和前端是互不影响的2个程序&#xff0c;那么我们前端应该如何从后台获取数据呢&#xff1f;因为是2个程序&#xff0c;所以…

pyinstaller 打包pyqt6等ui文件为exe可执行程序的方法

刚开始使用auto-py-to-exe打包pyqt6的程序&#xff0c;折腾好半天都会出错&#xff0c;关键打包出来的exe单文件有快100兆了&#xff0c;真大啊&#xff01; auto-py-to-exe有图形界面&#xff0c;看起来比较直观。 还有中文语言&#xff0c;对使用者比较友善&#xff0c;可以…

Vue3新增加的css语法糖

一、deep <template><div class""><el-input /> </div> </template> <style scoped> /* 样式穿透 */ :deep input {background: red; } </style> 二、slotted 子组件修改插槽里面的样式 <template><div clas…

【开源】基于Vue.js的衣物搭配系统的设计和实现

项目编号&#xff1a; S 016 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S016&#xff0c;文末获取源码。} 项目编号&#xff1a;S016&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 衣物档案模块2.2 衣物搭配模块2.3 衣…

python运算符重载之构造函数和迭代器

1 python运算符重载之构造函数和迭代器 python运算符重载是在类方法中拦截内置操作-当类的实例使用内置操作时&#xff0c;pytho自动调用对应方法&#xff0c;并且返回操作结果。 NO#描述1拦截运算运算符重载拦截内置操作&#xff0c;比如打印、函数调用、点号运算、表达式运…