写点什么

Vue3 知识点梳理(一)

作者:青柚1943
  • 2022 年 8 月 16 日
    湖南
  • 本文字数:3666 字

    阅读完需:约 12 分钟

Vue3知识点梳理(一)

1 全局 API

1.1 应用实例

#createApp()

第一个参数是根组件;第二个参数可选,它是要传递给根组件的 props

function createApp(rootComponent: Component, rootProps?: object): App
复制代码

#app.mount()

将应用实例挂载在一个容器元素中。

interface App { mount(rootContainer: Element | string): ComponentPublicInstance }
复制代码


/***引用自Element-Plus-Admin Main.ts ***/import { createApp } from 'vue'import App from './App.vue'//...
// 创建实例const setupAll = async () => { const app = createApp(App) await setupI18n(app) setupStore(app) setupElementPlus(app) setupRouter(app) //... app.mount('#app')}
setupAll()
复制代码


Source

#app.provide()

提供一个值,可以在应用中的所有后代组件中注入使用,可解决Prop 逐级透传问题

第一个参数应当是注入的 key,第二个参数则是提供的值。返回应用实例本身。

interface App {  provide<T>(key: InjectionKey<T> | symbol | string, value: T): this}
app.provide('message', 'hello')
复制代码


export default {  inject: ['message'],//注入上层组件提供的数据,需使用 inject 选项来声明  created() {    console.log(this.message) // 'hello'  }}
复制代码


#app.component()

如果同时传递一个组件名字符串及其定义,则注册一个全局组件;如果只传递一个名字,则会返回用该名字注册的件(如果存在的话)。

//定义interface App {  component(name: string): Component | undefined  component(name: string, component: Component): this}
// 注册一个选项对象app.component('my-component', { /* ... */})
// 得到一个已注册的组件const MyComponent = app.component('my-component')
复制代码


#app.directive()


如果同时传递一个名字和一个指令定义,则注册一个全局指令;如果只传递一个名字,则会返回用该名字注册的指令(如果存在的话)

interface App {  directive(name: string): Directive | undefined  directive(name: string, directive: Directive): this}
// 注册(对象形式的指令)app.directive('my-directive', { /* 自定义指令钩子 */})//e.g.const permiDirective: Directive = { mounted}const myDirective = app.directive('hasPermi',permiDirective)//使用v-hasPermi
// 注册(函数形式的指令)app.directive('my-directive', () => { /* ... */})//e.g.app.directive('focus',{ //v-focus // 当被绑定的元素插入到DOM的时候执行.. mounted(el){ el.focus(); }})
// 得到一个已注册的指令const myDirective = app.directive('my-directive')
复制代码

1.2 通用 API

#nextTick()

等待下一次 DOM 更新刷新的工具方法。当你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个 "tick" 才一起执行。这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。(使用场景

function nextTick(callback?: () => void): Promise<void>
const getForm = async () => { await nextTick() const form = unref(formRef) //function unref<T>(ref: T | Ref<T>): T if (!form) { console.error('The form is not registered. Please use the register method to register') } return form }
复制代码

#defineComponent()

在定义 Vue 组件时提供类型推导的辅助函数(为了 ts 代码提供类型推导,让 Vue 能解析组件中的属性)。

function defineComponent(  component: ComponentOptions | ComponentOptions['setup']): ComponentConstructor
const Foo = defineComponent(/* ... */)
type FooInstance = InstanceType<typeof Foo>//这里ts是能推断出组件Foo的类型,否则是Object
复制代码

2 组合式 API

2.1 响应式 API

#ref()

接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value

function ref<T>(value: T): Ref<UnwrapRef<T>>
interface Ref<T> { value: T}
复制代码

#computed ()

接受一个 getter 函数,返回一个只读的响应式 ref 对象。该 ref 通过.value 暴露 getter 函数的返回值。

计算属性值会基于其响应式依赖被缓存一个计算属性仅会在其响应式依赖更新时才重新计算。

(TIP:推荐使用计算属性,而不是用函数,特别是复杂逻辑)

// 是否是移动端const mobile = computed(() => useAppStore().getMobile)
复制代码

#reactive()

返回一个对象的响应式代理。(基本类型不要用它,要用 ref 函数

响应式转换是“深层”的:它会影响到所有嵌套的属性。一个响应式对象也将深层地解包任何 ref 属性,同时保持响应性。

const state = reactive({closeBoxTop: 20})
复制代码

#watch()

侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数。

// 侦听单个来源function watch<T>(  source: WatchSource<T>, //函数返回值,响应式对象,ref  callback: WatchCallback<T>, //三个参数:新值、旧值、注册副作用清理的回调函数  options?: WatchOptions //deep:深度监听): StopHandle
//监听路由变化watch( () => route.path, (newVal) => { console.log(newVal) })
复制代码

#unref()

如果参数是 ref,则返回内部值,否则返回参数本身。

function unref<T>(ref: T | Ref<T>): T
function getNumber(x: number | Ref<number>) { // unwrapped 现在保证为 number 类型 const unwrapped = unref(x)}
复制代码

#toRef()

const state = reactive({  foo: 1,  bar: 2})//toRef接收两个参数,第一个参数是哪个对象,第二个参数是对象的哪个属性const fooRef = toRef(state, 'foo')
复制代码

TIP:

(1) ref 本质是拷贝,修改响应式数据不会影响原始数据;toRef 的本质是引用关系,修改响应式数据会影响原始数据

(2) ref 数据发生改变,界面会自动更新;toRef 当数据发生改变是,界面不会自动更新

#toRefs()

将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef( ) 创建的。

function useFeatureX() {  const state = reactive({    foo: 1,    bar: 2  })
// ...基于状态的操作逻辑
// 在返回时都转为 ref return toRefs(state)}
// 可以解构而不会失去响应性const { foo, bar } = useFeatureX()
复制代码

#shallowRef

ref() 的浅层作用形式。浅层 ref 的内部值将会原样存储和暴露,并且不会被深层递归地转为响应式。

(常常用于对大型数据结构的性能优化或是与外部的状态管理系统集成。)


2.2 生命周期函数

#onMounted()

注册一个回调函数,在组件挂载完成后执行。这个钩子通常用于执行需要访问组件所渲染的 DOM 树相关的副作用。

function onMounted(callback: () => void): void
// 初始化所有主题色onMounted(() => { useAppStore().setCssVarTheme()})
复制代码

#onUpdated()

注册一个回调函数,在组件因为响应式状态变更而更新其 DOM 树之后调用。这个钩子会在组件的任意 DOM 更新后被调用,这些更新可能是由不同的状态变更导致的。如果你需要在某个特定的状态更改后访问更新后的 DOM,请使用  nextTick() 作为替代。

注:不要在 updated 钩子中更改组件的状态,这可能会导致无限的更新循环!!!

function onUpdated(callback: () => void): void
复制代码

#onUnmounted()

注册一个回调函数,在组件实例被卸载之后调用。

//组件卸载之前移除TimeronUnmounted(() => {    clearInterval(workTimer)})
复制代码

#onBeforeMount()

注册一个钩子,在组件被挂载之前被调用。

当这个钩子被调用时,组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。它即将首次执行 DOM 渲染过程。

#onBeforeUpdate

注册一个钩子,在组件即将因为响应式状态变更而更新其 DOM 树之前调用。

#onBeforeUnmount()

注册一个钩子,在组件实例被卸载(摧毁)之前调用。

function onBeforeUnmount(callback: () => void): void
复制代码

2.3 依赖注入

#provide()

provide() 接受两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,第二个参数是要注入的值。

function provide<T>(key: InjectionKey<T> | string, value: T): void
复制代码

#inject()

注入一个由祖先组件或整个应用 (通过 app.provide()) 提供的值。

第一个参数是注入的 key。Vue 会遍历父组件链,通过匹配 key 来确定所提供的值。如果父组件链上多个组件对同一个 key 提供了值,那么离得更近的组件将会“覆盖”链上更远的组件所提供的值。如果没有能通过 key 匹配到值,inject() 将返回 undefined,除非提供了一个默认值。

// 没有默认值function inject<T>(key: InjectionKey<T> | string): T | undefined
// 带有默认值function inject<T>(key: InjectionKey<T> | string, defaultValue: T): T
复制代码

(注:provide()和 inject() 必须在组件的 setup() 阶段同步调用。)

一般 provide()和 inject()成对使用

//父组件provide('baTable', baTable)
//子组件const baTable = inject('baTable') as BaTable
复制代码


用户头像

青柚1943

关注

生命不息,代码不止。 2020.08.04 加入

老街坊,小弄堂,是属于那年代白墙黑瓦的淡淡的忧伤。

评论

发布
暂无评论
Vue3知识点梳理(一)_Vue3_青柚1943_InfoQ写作社区