持续更新
基础内容
SFC: Single File Component
选项式 API 和组合式 API
mustache 语法 (即双大括号{{}}) 只能用于文本插值。
reactive() 只适用于对象 (包括数组和内置类型,如 Map 和 Set)。此外,ref() 可以接受任何值类型,并创建一个对象,在 .value property 下暴露内部值。都创建的是JavaScript proxy
ref()创建的proxy在其模板渲染上下文的顶层 property 时支持自动解包,
在 Vue 模板内,JavaScript 表达式可以被使用在如下场景上:
- 在文本插值中 (双大括号)
- 在任何 Vue 指令 (以 v-开头的特殊 attribute) attribute 的值中
- 计算属性值会基于其响应式依赖被缓存,比方法更好,不会每次重新渲染都重新计算,只会在响应式依赖更新时重新计算。一个计算属性的声明中描述的是如何根据其他值派生一个值,因此计算函数的职责应该仅为计算和返回该值而非异步请求或者更改DOM。修改计算属性值也没有意义。
原理
在watcher中调用getter,执行addSub, 将target传入对应的dep; vue的实现本质就是如此
Vue中一个发布者observer会被多个订阅者watcher订阅,同时一个订阅者也会订阅多个发布者,是多对多的关系,watcher也可以叫做依赖,依赖于发布者的变化从而执行其绑定的回调,dep可以叫做订阅中心,负责维护订阅列表2.x defineProperty 和 3.x Proxy 的区别:
2.x:
- 检测不到对象属性的添加和删除
- 数组API方法无法监听到
- 需要对每个属性进行遍历监听,如果嵌套对象,需要深层监听,造成性能问题
3.x
- Proxy可以直接监听数组的变化(- push、- shift、- splice)
- Proxy直接可以劫持整个对象,并返回一个新对象,我们可以只操作新的对象达到响应式目的
- 当对象嵌套对象时,递归响应式 - //实现深层响应式 function reactive(obj){ if(typeof obj!=='object' || obj===null){ return obj; } const observed = new Proxy(obj,{ get(target,key,reciver){ const res = Reflect.get(target,key,reciver); console.log(`getting ${key}:${res}`); return isObject(res)?reactive(res):res; }, }); return observed; }
- Proxy有多达13种拦截方法,不限于- apply、- ownKeys、- deleteProperty、- has等等,这是- Object.defineProperty不具备的- 正因为 - defineProperty自身的缺陷,导致- Vue2在实现响应式过程需要实现其他的方法辅助(如重写数组方法、增加额外- set、- delete方法)
vue指令
- 某些指令会需要一个“参数”,在指令名后通过一个冒号隔开做标识。 - 可以在绑定的表达式中使用一个组件暴露的方法 - <span :title="toTitleDate(date)"> {{ formatDate(date) }} </span>- 在指令参数上也可以使用一个 JavaScript 表达式,需要包含在一对方括号内,称作动态参数 - <p :[attributename]="attributeValue"></p> //动态参数期望值为字符串或 null ,null 代表显式移除该绑定,在HTML文件中时还要避免大写字母- 修饰符是以点开头的特殊后缀,表明指令需要以一些特殊的方式被绑定。例如 - .prevent修饰符会告知- v-on指令对触发的事件调用- event.preventDefault()- <form @submit.prevent="onSubmit">...</form>
- v-html=”html” - 具有v-html属性的对应标签的innderHTML 会与html变量值保持一致 
- v-bind:attributeName=”varName” 给 attribute 绑定一个动态值 
 abbreviated. :attribute=””
 布尔型attribute根据值为true/false来决定标签行为,下例中 isButtonDisabled 为非false布尔值或空字符串时,元素的disable属性值均为true- <button :disabled="isButtonDisabled">Button</button>- 还可以通过不带参数的 v-bind 将包含多个 attribute 的JavaScript 对象绑定到单个元素 - <script> const objectOfAttrs = { id: 'container', class: 'wrapper' }; </script> <template> <div v-bind="objectOfAttrs"></div> </template>
- v-on:DOMEventName=”funcName” 监听DOM事件 
 abbreviated. @DOMEventName=””
- 可以同时使用 v-bind 和 v-on 来在表单的输入元素上创建双向绑定: - <input :value="text" @input="onInput">- v-model是以上操作的语法糖 - <input v-model="text">- v-model 会将被绑定的值与 - <input>的值自动同步
- v-if=”varName” 条件渲染DOM元素,为真值时渲染,否则移除该DOM元素 - <h1 v-if="awesome">Vue is awesome!</h1>- 类似的有v-else和v-else-if可以与其配合使用,一个 - v-else和- v-else-if元素必须跟在一个- v-if或者- v-else-if元素后面,否则将不会识别它。
- v-show#- 另一个可以用来按条件显示一个元素的指令是 - v-show。其用法基本一样:- template - <h1 v-show="ok">Hello!</h1>- 不同之处在于 - v-show会在 DOM 渲染中保留该元素;- v-show仅切换了该元素上名为- display的 CSS 属性。- v-show不支持在- <template>元素上使用,也不能和- v-else搭配使用。
- v-for - 以下代码能创建多个li元素 - <li v-for="todo in todos" :key="todo.id"> <input type="checkbox" v-model="todo.done"> ... </li>- key# - key这个特殊的 attribute 主要作为 Vue 的虚拟 DOM 算法提示,在比较新旧节点列表时用于识别 vnode。- 预期: - number | string | symbol
- 详细信息 - 在没有 key 的情况下,Vue 将使用一种最小化元素移动的算法,并尽可能地就地更新/复用相同类型的元素。如果传了 key,则将根据 key 的变化顺序来重新排列元素,并且将始终移除/销毁 key 已经不存在的元素。 - 同一个父元素下的子元素必须具有唯一的 key。重复的 key 将会导致渲染异常。 - 最常见的用例是与 - v-for结合:- template - <ul> <li v-for="item in items" :key="item.id">...</li> </ul>- 也可以用于强制替换一个元素/组件而不是复用它。当你想这么做时它可能会很有用: - 在适当的时候触发组件的生命周期钩子
- 触发过渡
 - 举例来说: - template - <transition> <span :key="text">{{ text }}</span> </transition>- 当 - text变化时,- <span>总是会被替换而不是更新,因此 transition 将会被触发。
 
readonly 和 shallowreadonly
模板引用
为dom元素加上ref属性,在script中命名同名响应式属性即可操作模板
<script setup>
import { ref, onMounted } from 'vue'
// 声明一个 ref 来存放该元素的引用
// 必须和模板里的 ref 同名
const input = ref(null)
onMounted(() => {
  input.value.focus()
})
</script>
<template>
  <input ref="input" />
</template>响应式
reactive解构赋值便不再具有响应式,但是computed返回的内容是具有响应式的。
计算属性
计算属性的计算函数应只做计算而没有任何其他的副作用,一个计算属性的声明中描述的是如何根据其他值派生一个值。同时避免直接修改计算属性值。
从计算属性返回的值是派生状态。可以把它看作是一个“临时快照”,每当源状态发生变化时,就会创建一个新的快照。更改快照是没有意义的,因此计算属性的返回值应该被视为只读的,并且永远不应该被更改——应该更新它所依赖的源状态以触发新的计算。
// 组件中
function calculateBooksMessage() {
  return author.books.length > 0 ? 'Yes' : 'No'
}也可以同时传入 get 和 set 方法,超过只读范围来刻意产生副作用,此时传递给computed的是带有set和get方法的对象
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
  // getter
  get() {
    return firstName.value + ' ' + lastName.value
  },
  // setter
  set(newValue) {
    // 注意:我们这里使用的是解构赋值语法
    [firstName.value, lastName.value] = newValue.split(' ')
  }
})侦听器
watch:watch是去监听一个值的变化,然后执行相对应的函数。
如果监听的数据源是一个 引用类型 时( e.g. Object 、 Array 、 Date … ), value 和 oldValue 是完全相同的,因为指向同一个对象。
// watch 部分的 TS 类型
// ...
export declare function watch<T, Immediate extends Readonly<boolean> = false>(
  source: WatchSource<T>,
  cb: WatchCallback<T, Immediate extends true ? T | undefined : T>,
  options?: WatchOptions<Immediate>
): WatchStopHandlecallback 有三个参数,依次为 value、oldValue、onCleanup清理函数。
还可以做批量监听,参数以数组形式传入,在回调函数中也以数组形式作为参数传入
watch 的第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组:
const x = ref(0)
const y = ref(0)
// 单个 ref
watch(x, (newX) => {
  console.log(`x is ${newX}`)
})
// getter 函数
watch(
  () => x.value + y.value,
  (sum) => {
    console.log(`sum of x + y is: ${sum}`)
  }
)
// 多个来源组成的数组
watch([x, () => y.value], ([newX, newY]) => {
  console.log(`x is ${newX} and y is ${newY}`)
})关于 options
| deep | boolean | false | true | false | 是否进行深度监听,适用于监听 ref 响应式引用对象 | 
|---|---|---|---|---|
| immediate | boolean | false | true | false | 是否立即执行监听回调,包括初始化,为 false 时初始化不调用回调 | 
| flush | string | ‘pre’ | ‘pre’ | ‘post’ | ‘sync’ | 控制监听回调的调用时机 | 
| onTrack | (e) => void | 在数据源被追踪时调用 | ||
| onTrigger | (e) => void | 在监听回调被触发时调用 | 
deep在传入为 reactive 时自动开启,可以搭配传入 ref 引用对象使用
在带有 immediate 选项时,不能在第一次回调时取消该数据源的监听
定义一个 watch 行为的时候,它会返回一个用来停止监听的函数
模板引用
使用 ref 在dom 中挂载结点,必须使用 xxx.value 才能访问到模板 dom 元素
组件
注册
全局注册和局部注册,3.2之后好像局部注册就够了
Props
组件间传递值
在子组件中定义属性向外暴露,外部组件用 v-bind 传递进来,
<script setup>
const props = defineProps(['foo'])
console.log(props.foo)
    
//or
// 使用 <script setup>
defineProps({
  title: String,
  likes: Number
})
</script>在ts中
<script setup lang="ts">
defineProps<{
  title?: string
  likes?: number
}>()
</script>
透传attrs
非props,直接赋值
v-on 监听器继承#
同样的规则也适用于 v-on 事件监听器:
template
<MyButton @click="onClick" />click 监听器会被添加到 <MyButton> 的根元素,即那个原生的 <button> 元素之上。当原生的 <button> 被点击,会触发父组件的 onClick 方法。同样的,如果原生 button 元素自身也通过 v-on 绑定了一个事件监听器,则这个监听器和从父组件继承的监听器都会被触发。
深层组件继承#
有些情况下一个组件会在根节点上渲染另一个组件。例如,我们重构一下 <MyButton>,让它在根节点上渲染 <BaseButton>:
template
<!-- <MyButton/> 的模板,只是渲染另一个组件 -->
<BaseButton />- 透传的 attribute 不会包含 <MyButton>上声明过的 props 或是针对emits声明事件的v-on侦听函数,换句话说,声明过的 props 和侦听函数被<MyButton>“消费”了。
- 透传的 attribute 若符合声明,也可以作为 props 传入 <BaseButton>。
禁用attrs:如果你不想要一个组件自动地继承 attribute,你可以在组件选项中设置 inheritAttrs: false。
管理所有透传attrs
const attrs = useAttrs();
事件
组件直接传递事件,Child.vue 通过 emit 向 Father.vue 触发父组件的事件执行
和原生 DOM 事件不一样,组件触发的事件没有冒泡机制。你只能监听直接子组件触发的事件。平级组件或是跨越多层嵌套的组件间通信,应使用一个外部的事件总线,或是使用一个全局状态管理方案
defineEmits
emit
<script setup>
const emit = defineEmits(['inFocus', 'submit'])
function buttonClick() {
  emit('submit')
}
</script>这个 emits 选项还支持对象语法,它允许我们对触发事件的参数进行验证:
vue
<script setup>
const emit = defineEmits({
  submit(payload) {
    // 通过返回值为 `true` 还是为 `false` 来判断
    // 验证是否通过
  }
})
</script>插槽
<slot> 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。
插槽内容可以访问到父组件的数据作用域,无法访问子组件的数据
具名插槽
带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 <slot> 出口会隐式地命名为“default”
v-slot 有对应的简写 #,因此 <template v-slot:header> 可以简写为 <template #header>。其意思就是“将这部分模板片段传入子组件的 header 插槽中”。
当一个组件同时接收默认插槽和具名插槽时,所有位于顶级的非 <template> 节点都被隐式地视为默认插槽的内容。
例子:
待接收插槽内容的子组件
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
父组件
<BaseLayout>
  <template #header>
    <h1>Here might be a page title</h1>
  </template>
  <!-- 隐式的默认插槽 -->
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  <!-- 
    <template #default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
    </template> 
    -->
  <template #footer>
    <p>Here's some contact info</p>
  </template>
</BaseLayout>
子组件渲染结果
<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>
支持动态指令参数
<template v-slot:[dynamicSlotName]>
  ...
</template>
<!-- 缩写为 -->
<template #[dynamicSlotName]>
  ...
</template>依赖注入
祖先组件中用provide提供依赖,后代任意位置可使用inject注入该依赖
//祖先
const message = ref('hello')
provide('message', message)//name, value
//后代
const message = inject('message')//name生命周期
created:html加载完成之前,执行。执行顺序:父组件-子组件
mounted:html加载完成后执行。执行顺序:子组件-父组件
methods:事件方法执行
created():组件实例创建完成,dom还未生成,仅仅触发一次; mounted是挂载vue实例后的钩子函数,仅仅执行一次; activated():在使用时,会用到activated(),keep-live主要目的是可以使用缓存,避免组件重新渲染;
activated()只要进入页面就会触发

全局API
nextTick()#
等待下一次 DOM 更新刷新的工具方法。
- 类型 - function nextTick(callback?: () => void): Promise<void>
- 详细信息 - 当你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。 - nextTick()可以在状态改变后立即使用,以等待 DOM 更新完成。你可以传递一个回调函数作为参数,或者 await 返回的 Promise。
路由vue-router
- router-link - 链接,类似a标签,但是自定义组件,使得 Vue Router 可以在不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码 - //如导航代码 <router-link class="nav-link" to="ContactUs">联系我们</router-link> 12- 通过router-link可以使 - <router-view/>中的显示内容路由(跳转)到- src/router/index.js文件中配置的组件中去,这类似于html的a标签中的href(注意:href页面会刷新,在这里则不会),其实这就好比tab选项卡中的头部选项,- router-view好比tab选项卡的body选项。
- router-view - 显示与 url 对应的组件 - 默认刚进入网页时是’/‘ - <router-view><router-view/>(命名视图) 1 <router-view/>(嵌套命名视图) 1- <router-view>是用来渲染通过路由映射过来的组件,当路径更改时, 其中的内容也会发生更改- 主要应用于单页面中,与 - router-link配合,渲染- router-link映射过来的组件。- 运作过程:就是几个跳转链接跳到对应的子页面,程序运行的时候,会将 - <template>标签里面的内容都注入到App.vue页面中的- router-view标签中,从而实现无刷新的路由跳转。
- createRouter(RouterOptions ) - RouterOptions extends PathParserOptions{  history: RouterHistory;  routes: RouteRecordRaw[]; }
- useRoute# - 返回当前路由地址。相当于在模板中使用 - $route。必须在- setup()中调用。- 函数签名: - export declare function useRoute(): RouteLocationNormalized- useRouter# - 返回 router 实例。相当于在模板中使用 - $router。必须在- setup()中调用。- 函数签名: - export declare function useRouter(): Router
- 
创建一个 HTML5 历史,即单页面应用程序中最常见的历史记录。应用程序必须通过 http 协议被提供服务。 可选参数base为托管目录 createWebHistory() // 没有 base,应用托管在域名 `https://example.com` 的根目录下。 createWebHistory('/folder/') // 给出的网址为 `https://example.com/folder/`
- router.push# - 通过在历史堆栈中推送一个 entry,以编程方式导航到一个新的 URL。 - 函数签名: - push(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>- 参数 - 参数 - 类型 - 描述 - to - RouteLocationRaw- 要导航到的路由地址 
ts类型
- RouteRecordRaw - export declare type RouteRecordRaw = RouteRecordSingleView | RouteRecordMultipleViews | RouteRecordRedirect;
- RouteLocationNormalized - export declare interface RouteLocationNormalized extends _RouteLocationBase { /** * Array of {@link RouteRecordNormalized} */ matched: RouteRecordNormalized[]; } export declare interface _RouteLocationBase extends Pick<MatcherLocation, 'name' | 'path' | 'params' | 'meta'> { /** * The whole location including the `search` and `hash`. This string is * percentage encoded. */ fullPath: string; /** * Object representation of the `search` property of the current location. */ query: LocationQuery; /** * Hash of the current location. If present, starts with a `#`. */ hash: string; /** * Contains the location we were initially trying to access before ending up * on the current location. */ redirectedFrom: RouteLocation | undefined; } declare interface MatcherLocation { /** * Name of the matched record */ name: RouteRecordName | null | undefined; /** * Percentage encoded pathname section of the URL. */ path: string; /** * Object of decoded params extracted from the `path`. */ params: RouteParams; /** * Merged `meta` properties from all the matched route records. */ meta: RouteMeta; /** * Array of {@link RouteRecord} containing components as they were * passed when adding records. It can also contain redirect records. This * can't be used directly */ matched: RouteRecord[]; }
- Router 属性# - currentRoute# - 类型:Ref 
- 详细内容: - 当前路由地址。只读的。 
 - options# 
- 详细内容: - 创建 Router 时传递的原始配置对象。只读的。 
 
状态管理工具
Vuex
中大型项目
Pinia
小型项目
一个 Store (如 Pinia)是一个实体,它持有未绑定到您的组件树的状态和业务逻辑。换句话说,它托管全局状态。它有点像一个始终存在并且每个人都可以读取和写入的组件。它有三个概念,state、getters 和 actions 并且可以安全地假设这些概念等同于组件中的“数据”、“计算”和“方法”。
可以通过调用 store 上的 $reset() 方法将状态 重置 到其初始值:
const store = useStore()
store.$reset()构建工具
vite
Vite 在一个特殊的 import.meta.env 对象上暴露环境变量。这里有一些在所有情况下都可以使用的内建变量:
- import.meta.env.MODE: {string} 应用运行的模式。- 默认情况下,开发服务器 (dev命令) 运行在development(开发) 模式,而build命令则运行在production(生产) 模式。
 
- 默认情况下,开发服务器 (
- import.meta.env.BASE_URL: {string} 部署应用时的基本 URL。他由- base配置项决定。
- import.meta.env.PROD: {boolean} 应用是否运行在生产环境。
- import.meta.env.DEV: {boolean} 应用是否运行在开发环境 (永远与- import.meta.env.PROD相反)。
- import.meta.env.SSR: {boolean} 应用是否运行在 server 上。
不支持动态读取值。在生产环境中,这些环境变量会在构建时被静态替换,例如,动态 key 取值 import.meta.env[key] 是无效的。
配置
- base¶ - 类型: string
- 默认: /
 - 开发或生产环境服务的公共基础路径。合法的值包括以下几种: - 绝对 URL 路径名,例如 /foo/
- 完整的 URL,例如 https://foo.com/
- 空字符串或 ./(用于嵌入形式的开发)
 
- 类型: 
- plugins¶ - 类型: (Plugin | Plugin[] | Promise<Plugin | Plugin[]>)[]
 - 需要用到的插件数组。Falsy 虚值的插件将被忽略,插件数组将被扁平化(flatten)。查看 插件 API 获取 Vite 插件的更多细节。 
- 类型: 
- server - .host¶ - 类型: string | boolean
- 默认: 'localhost'
 - 指定服务器应该监听哪个 IP 地址。 如果将此设置为 - 0.0.0.0或者- true将监听所有地址,包括局域网和公网地址。localhost一般用来测试本机,监听本机请求。
- 类型: 
- .port - 类型: number
- 默认值: 5173
 - 指定监听端口。注意:如果端口已经被使用,Vite 会自动尝试下一个可用的端口,所以这可能不是开发服务器最终监听的实际端口。 
- 类型: 
 
UI框架
element-plus
el-input
el-button
| 属性名 | 说明 | 类型 | 可选值 | 默认值 | 
|---|---|---|---|---|
| size | 尺寸 | string | large / default /small | — | 
| type | 类型 | string | primary / success / warning / danger / info / | — | 
详见https://element-plus.gitee.io/zh-CN/component/button.html#button-%E5%B1%9E%E6%80%A7
el-dialog
| 属性名 | 说明 | 类型 | 可选值 | 默认值 | 
|---|---|---|---|---|
| model-value / v-model | 是否显示 Dialog | boolean | — | — | 
| title | Dialog 对话框 Dialog 的标题, 也可通过具名 slot (见下表)传入 | string | — | — | 
| width | Dialog 的宽度 | string / number | — | 50% | 
| fullscreen | 是否为全屏 Dialog | boolean | — | false | 
| top | Dialog CSS 中的 margin-top 值 | string | — | 15vh | 
| modal | 是否需要遮罩层 | boolean | — | true | 
| lock-scroll | 是否在 Dialog 出现时将 body 滚动锁定 | boolean | — | true | 
| open-delay | Dialog 打开的延时时间,单位毫秒 | number | — | 0 | 
| close-delay | Dialog 关闭的延时时间,单位毫秒 | number | — | 0 | 
| close-on-click-modal | 是否可以通过点击 modal 关闭 Dialog | boolean | — | true | 
| close-on-press-escape | 是否可以通过按下 ESC 关闭 Dialog | boolean | — | true | 
| show-close | 是否显示关闭按钮 | boolean | — | true | 
| before-close | 关闭前的回调,会暂停 Dialog 的关闭. 回调函数内执行 done 参数方法的时候才是真正关闭对话框的时候. | Function(done) (done 用来关闭 Dialog) | — | — | 
https://element-plus.gitee.io/zh-CN/component/dialog.html#%E5%B1%9E%E6%80%A7
el-drawer*
el-upload*
Form
FormInstance类型,可以辅助vue3中的ref属性为dom操作提供便利,
方法
- validate - //类型 (callback?: (isValid: boolean, invalidFields?: ValidateFieldsError) => void) => Promise<void>
- validator:自定义校验规则 - 为指定字段定制验证函数 - const fields = { field: { validator(rule, value, callback) { return value === 'test'; }, message: 'Value is not equal to "test".', }, field2: { validator(rule, value, callback) { return new Error(`${value} is not equal to 'test'.`); }, }, arrField: { validator(rule, value) { return [ new Error('Message 1'), new Error('Message 2'), ]; }, }, };- asyncValidator 
- FormItemRule - export declare type Arrayable<T> = T | T[]; export interface FormItemRule extends RuleItem { trigger?: Arrayable<string>; } export interface RuleItem { type?: RuleType; required?: boolean; pattern?: RegExp | string; min?: number; max?: number; len?: number; enum?: Array<string | number | boolean | null | undefined>; whitespace?: boolean; fields?: Record<string, Rule>; options?: ValidateOption; defaultField?: Rule; transform?: (value: Value) => Value; message?: string | ((a?: string) => string); asyncValidator?: (rule: InternalRuleItem, value: Value, callback: (error?: string | Error) => void, source: Values, options: ValidateOption) => void | Promise<void>; validator?: (rule: InternalRuleItem, value: Value, callback: (error?: string | Error) => void, source: Values, options: ValidateOption) => SyncValidateResult | void; }
Icon
https://element-plus.gitee.io/zh-CN/component/icon.html
ElMessage
配置项
| 属性 | 说明 | 类型 | 默认值 | 
|---|---|---|---|
| message | 消息文字 | `string | VNode | 
| type | 消息类型 | `’success’ | ‘warning’ | 
| icon | 自定义图标,该属性会覆盖 type的图标。 | `string | Component` | 
| dangerouslyUseHTMLString | 是否将 message 属性作为 HTML 片段处理 | boolean | false | 
| custom-class | 自定义类名 | string | — | 
| duration | 显示时间,单位为毫秒。 设为 0 则不会自动关闭 | number | 3000 | 
| show-close | 是否显示关闭按钮 | boolean | false | 
| center | 文字是否居中 | boolean | false | 
| on-close | 关闭时的回调函数, 参数为被关闭的 message 实例 | function | — | 
| offset | Message 距离窗口顶部的偏移量 | number | 20 | 
| appendTo | 设置组件的根元素 | `string | HTMLElement` | 
| grouping | 合并内容相同的消息,不支持 VNode 类型的消息 | boolean | false | 
例子
ElMessage({
    message: data.error,
    type: 'error',
    duration: 1.5 * 1000,
});
//显示错误信息
const open4 = () => {
  ElMessage.error('Oops, this is a error message.')
}底层
compiler-sfc
vue的直属目录下有一个 compiler-sfc
compiler-sfc,这个文件夹里面的内容主要是能够编译 template,style, script(setup)的字符串,生成对应的内容。
分别对应的是 compileTemplate,compileStyle, compileScript
