简介
来自官网 https://cn.vuejs.org
1. 注册
在使用一个 Vue 组件之前,要先注册。
1.1 全局注册
在全局注册的组件,可以在此应用的任意组件的模板中使用。
使用应用实例的 app.component()
方法:
全局注册的问题:
在打包的时候不能被 tree-shaking
在大型项目中让项目的依赖关系变得不那么明确
可能会影响项目的后续维护,类似使用过多的全局变量一样
1.2 局部注册
在使用它的父组件中显式导入,只能在父组件中使用,不能在后代组件中使用。
在使用
<script setup>
的单文件组件中,导入的组件可以直接在模板中使用,无需注册否则就需要使用
components
选项来显式注册
局部注册的优点:
使组件之间的依赖关系更加明确
并且对 tree-shaking 更加友好
1.3 组件名
建议使用 PascalCase(驼峰式)<PascalCase />
:
可在模板中区分原生 HTML 元素和 web components(单文件组件和内联字符串模板)
在 DOM 模板中 PascalCase 标签名是不可用的
2. Props 声明
一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute。
2.1 方式
使用
defineProps()
宏使用
props
选项
这声明方式的背后使用的都是 prop
选项,它们都分别支持数组格式和对象格式。比如:
其中,对象格式的 prop,包括了名称+预期类型的构造函数(方便 prop 校验)。构造函数可以是原生构造函数,也可以是自定义的类或构造函数。
2.2 名字和值
prop 的名字
camelCase 式(DOM 模板除外)的好处(但优势不明显)
是合法的 JavaScript 标识符,可以直接在模板的表达式中用
可以避免在作为属性 key 名时必须加引号
推荐用 kebab-case 形式,可以和 HTML attribute 对齐
<BlogPost title="My journey with Vue" />
与默认 attribute 对齐了更舒服些
prop 的值:任何类型的值
2.3 单向数据流
props 只能从父到子组件,而不会逆向传递。
如果想要更改一个 prop,可以用以下方式:
prop 用来接收初始值,子组件再定义个局部数据属性
基于 prop 的计算属性
子组件抛出个事件来通知父组件更改数据(尤其是对引用型的 prop)
3. 事件
3.1 触发和监听
触发和监听事件:在
v-on
(简写为@
)上子组件:触发自定义事件,通过
$emit()
方法父组件:监听事件
关于组件自己触发的事件的说明
格式支持自动转换,用 camelCase 触发,用 kebab-case 来监听(同组件的 prop)
支持事件修饰符、可以带参数
重名:如果和原生事件重名,则监听器只会监听组件触发的那个,而不再响应原生事件
没有冒泡:只能监听直接子组件触发的事件
如果要在平级组件或是跨越多层嵌套的组件间通信,可以
使用一个外部的事件总线
使用一个全局状态管理方案
3.2 声明要触发的事件
推荐总是显式地声明组件要触发的事件:
若是
<script setup>
则用defineEmits()
宏若是
setup()
则用emits
选项同样,支持数组、对象(对触发事件的参数进行验证)
3.3 让组件支持 v-model
v-model
两种方法:
子组件内部要做的两件事
将内部原生
input
元素的value
attribute 绑定到modelValue
prop输入新的值时在
input
元素上触发update:modelValue
事件
子组件使用一个可写的,同时具有 getter 和 setter 的计算属性
get
方法需返回modelValue
propset
方法需触发相应的事件
eg. 方法一
eg. 方法二
默认情况,v-model
在组件上都是使用 modelValue
作为 prop,并以 update:modelValue
作为对应的事件。我们可以通过给 v-model
指定一个参数来更改这些名字,这样就能轻松实现多个 v-model
绑定了。
此外,我们还可以让一个自定义组件的 v-model
支持自定义的修饰符。
4. 透传 attributes
自动透传 + 自动连续透传 + 自动合并
不包括组件自己声明为
props
和emits
的 attribute自动合并:从父元素上继承的和子元素根元素自己的
禁用 Attributes 继承:
inheritAttrs: false
适用场景:需应用在根节点以外的其他元素上
访问方法:
模板:可用
$attrs
访问到在
<script setup>
中使用useAttrs()
API在
setup()
函数中是上下文对象的一个属性ctx.attrs
注意事项:
透传 attributes 在 JavaScript 中保留了它们原始的大小写,不同于 props
v-on
事件@click
在数据上会显示为$attrs.onClick
多个根节点的组件:没有自动 attribute 透传行为,所以需要我们显式绑定
attr
对象不是响应式的(考虑到性能因素)。若想要响应式,可用 prop 或onUpdated()
5. 插槽
插槽 <slot>
可以让组件接收模板内容。
slot outlet,插槽出口,子组件里收
slot content,插槽内容,父组件里传
插槽内容可以是任意合法的模板内容,比如文本、多个元素、其它组件等,插槽让组件更加灵活和更具有可复用性。
5.1 slot outlet 和 slot content
默认内容
具名插槽:静态名字 + 动态名字
收:
<slot name="header"></slot>
插槽上的 name 是一个 Vue 特别保留的 attribute,不会作为 props 传递给插槽
传:
<template v-slot:header></template>
,简写为<template #header>
传:
<template #[dynamicSlotName]></template>
动态名字
其它情况
没有提供 name 的
<slot>
出口会隐式地命名为 'default'所有位于顶级的非
<template>
节点都被隐式地视为默认插槽的内容
5.2 插槽数据的作用域
可以访问到父组件的数据作用域,但无法访问子组件的数据。
Vue 模板中的表达式只能访问其定义时所处的作用域,这和 JavaScript 的词法作用域规则是一致的,也就是:父组件模板中的表达式只能访问父组件的作用域;子组件模板中的表达式只能访问子组件的作用域。
5.3 插槽数据也想访问子组件的
如果想要插槽的内容同时使用父组件域内和子组件域内的数据,可以在插槽出口(子组件)对插槽传递 props,详见作用域插槽(接收的参数只在该插槽作用域内有效)。
默认插槽传递和接收 props(下方示例)
具名插槽传递和接收 props
6. 依赖注入
父组件给子组件传递数据,两种方式:
props
:当层次太深时不方便provide
和inject
依赖提供者:父组件,也可以是整个应用实例层
app
任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖
6.1 provide 提供
使用 provide()
函数,向后代组件提供数据。
注入名:可以是字符串、Symbol(可以避免潜在的冲突)
注入值:任意类型,包括响应式的状态
6.2 inject 注入
使用 inject()
函数,来注入上层组件提供的数据:
7. 异步组件
作用:仅在需要时再从服务器加载相关组件
方法:
defineAsyncComponent()
,接收一个返回 Promise 的加载函数
eg1. ES 模块动态导入也会返回一个 Promise
eg2. 异步组件 + 内置的 <Suspense>
组件
8. 状态管理
每一个 Vue 组件实例都已经在“管理”它自己的响应式状态了:
状态:驱动整个应用的数据源
视图:对状态的一种声明式映射
交互:状态根据用户在视图中的输入而作出相应变更的可能方式
然而,当有多个组件共享一个共同的状态时,就没有这么简单了,比如多个视图可能都依赖于同一份状态,比如来自不同视图的交互也可能需要更改同一份状态。
可选的办法:
将共享状态“提升”到共同的祖先组件上去,再通过 props 传递下来
问题:prop 逐级透传问题,尤其是在深层次的组件树结构中的时候
抽取出组件间的共享状态,放在一个全局单例中来管理:用响应式 API 做简单状态管理,多个组件共用了单一的数据源
store
对象,代码示例如下。随之而来的问题:任意一个导入了
store
的组件都可以随意修改它的状态,不利于维护解决:在 store 上定义方法,方法名应该要能表达出行动的意图
可作为 store 的:单个响应式对象, 其它响应式 API:
ref()
,computed()
, 通过一个组合式函数来返回一个全局状态
利用服务端渲染 (SSR) 的应用
特殊之处:store 是跨多个请求共享的单例,详见服务端渲染-跨请求状态污染
官方的状态管理库 Pinia
Vue 之前的官方状态管理库是 Vuex,现在处于维护模式,但不再接受新的功能
相比于 Vuex,Pinia 提供了更简洁直接的 API,并提供了组合式风格的 API,最重要的是,在使用 TypeScript 时它提供了更完善的类型推导
eg. 用响应式 API 做简单状态管理(手动管理)
9. 更多
组件的封装原理
Last updated