记录每天自我学习转前端的碎碎念,仅作加强记忆的笔记和自我监督打卡使用。
queueMicrotask 是 JavaScript 提供的用于调度微任务(Microtask)的全局 API,其核心特性和用法如下:
一、核心功能与语法
queueMicrotask(callback)
- 参数:callback 为待执行的函数
- 行为:将回调函数加入 微任务队列,在当前宏任务(Macrotask)结束后、渲染前执行
二、执行时机对比
| 调度方式 | 队列类型 | 执行时机 | 典型场景 |
|---|---|---|---|
| queueMicrotask | 微任务队列 | 当前任务末尾,渲染前 | 状态更新、DOM 操作 |
| Promise.resolve().then() | 微任务队列 | 同 queueMicrotask | Promise 链式调用 |
| setTimeout | 宏任务队列 | 事件循环下一轮 | 延迟执行、异步调度 |
// 同步代码
console.log("Start");
// 调度微任务
queueMicrotask(() => {
console.log("Microtask executed");
});
// 同步代码继续
console.log("End");
/* 输出顺序:
Start
End
Microtask executed
*/
createApp 是 Vue 3 的核心 API
function createApp(rootComponent: Component, rootProps?: object): App
| 类型 | 是否必填 | 说明 |
|---|---|---|
| (rootComponent) Component | 是 | 根组件对象:包含模板、数据、生命周期等配置的 Vue 组件定义对象 |
| (rootProps) Object | 否 | 根组件 Props:传递给根组件的初始化属性(可选) |
import { createApp } from 'vue';
import App from './App.vue'; // 根组件文件
createApp(App, {
title: '控制台', // 字符串类型 Props
initialCount: 0, // 数字类型 Props
theme: 'dark' // 自定义配置项
}).mount('#app');
*第一个参数rootComponent创建方式
1.单文件组件(SFC)方式(主流实践)
<!-- App.vue -->
<template>
<div id="app">
<Header />
<RouterView />
<Footer />
</div>
</template>
<script setup>
import Header from './Header.vue'
import Footer from './Footer.vue'
</script>
2.对象字面量方式
const rootComponent = {
template: `
<div>
<h1>{{ title }}</h1>
<button @click="count++">点击: {{ count }}</button>
</div>
`,
data() {
return {
title: 'Vue 3 应用',
count: 0
}
},
mounted() {
console.log('根组件已挂载')
}
}
createApp(rootComponent).mount('#app')
// 这里的rootComponent是一个对象
3.组合式 API 方式
import { ref, onMounted } from 'vue'
const rootComponent = {
setup() {
const count = ref(0)
const title = ref('组合式根组件')
onMounted(() => {
console.log('组合式根组件挂载完成')
})
return { count, title }
},
template: `<div>{{ title }} - 计数: {{ count }}</div>`
}
createApp(rootComponent).mount('#app’)
// !!!注意,2和3的方式中如果不使用template模版,则需要实现render函数替代模板
说明
1.template 定义组件 HTML 结构(字符串模板或 DOM 选择器) template: <div>内容</div>
2.render 使用渲染函数替代模板 render() { return h('div') }
3.setup Composition API 入口,返回模板可用数据/函数 setup() { return { ref } }
4.data 返回初始响应式数据的函数(Options API) data() { return { count:0 } }
5.components 注册局部子组件 components: { MyButton }
6.props 声明接收的 Props(支持类型校验) props: { size: Number }
实现一个Vue 组件自动注册工具
import Button from './Button.vue'
export default withInstall(Button)
// __name:单文件组件(SFC)编译时自动添加的属性
export function withInstall(comp) {
const name = camelToKebabCase(comp.__name)
comp.__tagName = name
comp.install = (app) => {
install(app, comp)
}
return comp
}
function camelToKebabCase(str) {
return str
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2') // 处理连续大写
.replace(/([a-z])([A-Z])/g, '$1-$2')
.toLowerCase();
}
export function install(app, component) {
// 全局注册组件
app.component(
component.__tagName,
component,
)}
这段代码实现了一个 Vue 组件自动注册工具 withInstall,核心功能是为 Vue 组件添加全局安装能力
app.use是注册插件的
Vue 要求插件必须提供 install 方法,通过此函数统一暴露安装入口,使组件支持 app.use() 全局注册
// 使用示例
import MyComponent from './MyComponent.vue';
const app = createApp(App);
app.use(MyComponent); // 触发组件的install 方法,即comp.install
app.component 和 app.use
app.component() 注册全局组件 单组件定义 按钮、弹窗等复用UI元素
app.use() 安装功能插件 插件(含多组件/功能) 路由、状态管理、UI框架集成
在 Vue 3 中,createApp().use() 方法是用于安装 Vue.js 插件的核心 API;必须在 mount() 挂载应用前调用:
createApp().use() 其中use的有2个参数,第一个参数是必传的,类型是插件对象或者函数,第二个参数是可选的,作为第二个参数传递给插件的 install 方法:或者传递给函数的第二个参数
1.插件对象:必须包含 install 方法,Vue 自动调用该方法进行安装
app.use({
install(app, options) {
// 注册全局组件/指令等
}
},{size:1})
这里的{size:1}就会作为install的第二个参数options,第一个参数是固定的
2.插件函数:直接作为安装函数install执行,
app.use((app, options) => {
app.directive('focus', ...)
},{size:1})
// 这里的{size:1}就会传给参数options,第一个参数是固定的
在 Vue 3 中,createApp().component() 是用于全局注册组件的核心 API 方法。它通过 Vue 应用实例调用,允许你在整个应用中的任何位置使用注册的组件,无需重复导入
app.component(name: string, definition: Component);
// name:组件名称(字符串),如 'MyButton',在模板中使用时需转换为短横线命名(<my-button>)。
//definition:组件定义对象(Options API)或异步导入的组件(如defineAsyncComponent)。
全局可用性:注册后,该组件可在整个应用的所有子组件中直接使用,无需局部注册。
支持链式调用:可连续注册多个组件:
createApp({}).component('ComponentA', { }).component('ComponentB', { }).mount('#app');
definition:
1.选项式 API 对象:包含 template、data、methods 等选项的传统 Vue 组件配置:
template 定义组件的 HTML 结构(支持字符串模板或 #template 选择器)
data() 返回组件初始响应式数据的函数(必须为函数形式)
props 声明父组件传入的属性(支持类型校验和默认值)
methods 定义可在模板中调用的函数
setup() Composition API 入口,处理响应式状态和逻辑
components 注册局部子组件
app.component('MyComponent', {
__scopeId: `data-v-${options.id}`,
template: '<div>{{ message }}</div>',
data() {
return { message: 'Hello Vue!' }
},
methods: {
showAlert() {
alert(this.message);
}
}
})
!!!__scopeId在 Vue 组件中,__scopeId 是 Vue 内部用于实现 Scoped CSS(作用域样式) 的关键机制
- 样式作用域隔离__scopeId 是一个包含唯一哈希值的属性(如 data-v-5f3e9e),用于:
- 为组件内所有元素自动添加该属性选择器
- 确保 CSS 样式仅作用于当前组件
- 避免样式污染防止组件样式意外影响全局或其他组件,实现:css
/* 编译前 .btn { color: red; }
/* 编译后 .btn[data-v-5f3e9e] { color: red; }
技术实现原理
编译时注入当使用 时,Vue 编译器自动: 生成唯一哈希值(如 data-v-5f3e9e) 将其作为 __scopeId 注入组件选项 重写 CSS 选择器添加属性限定符
注意事项
非公开 API__scopeId 是 Vue 内部实现细节,不建议手动修改或依赖应通过 声明使用作用域样式
2.单文件组件(SFC):直接导入 .vue 文件作为组件定义:
import MyComponent from './MyComponent.vue';
app.component('MyComponent', MyComponent);
3.异步组件:使用 defineAsyncComponent 动态加载组件,优化性能:
import { defineAsyncComponent } from 'vue';
app.component('AsyncComponent', defineAsyncComponent(() =>
import('./AsyncComponent.vue')
));
在 Vue.js 中, 是一个内置的动态组件容器,通过 is 属性决定具体渲染的组件,高频切换时使用 keep-alive 避免重复渲染开销
<component :is="currentComponent"></component>
is 属性:接收组件名(字符串)或组件定义对象,动态决定渲染内容
<template>
<component :is="currentView" />
</template>
<script setup>
import { ref, shallowRef } from 'vue';
const views = {
asyncComp: defineAsyncComponent(() => import('./MyComponent.vue')),
normalComp: { template: '<div>普通组件</div>' }
};
const currentView = shallowRef(views.normalComp);
// 动态切换组件
function loadAsync() {
currentView.value = views.asyncComp;
}
</script>
resolveComponent
是用于按名称解析已注册组件的内部工具函数,主要在渲染函数和 setup() 中使用
1.按名称获取组件
通过组件名(字符串)查找全局或局部注册的组件定义:
import { resolveComponent } from 'vue';
const MyComponent = resolveComponent('MyComponent');
2.支持动态组件场景
配合 h() 或 <component :is> 实现动态渲染:
// 渲染函数中使用
render() {
const comp = resolveComponent(this.componentName);
return h(comp);
}
注意事项:组件需先通过 app.component() 或局部 components 注册,否则返回名称字符串并警告
查找顺序:当前组件局部注册 → 全局注册
在 Vue 3 中,h() 函数(全称 hyperscript)是用于创建虚拟 DOM 节点(vnode) 的核心 API,尤其在编写渲染函数(render function)时至关重要
一、核心作用
1.生成虚拟节点代替模板编译器,直接创建描述 DOM 结构的 JavaScript 对象(vnode)
import { h } from 'vue';
const vnode = h('div', { class: 'container' }, 'Hello Vue 3');
2.动态渲染基础
为 render() 函数和 JSX 提供底层实现能力
export default {
render() {
return h('button', { onClick: this.handleClick }, 'Submit');
}
}
二、参数详解
h() 接受三个核心参数:
h(type, props, children | slots);第三个参数不仅是子节点(字符串/数组/VNode)),也可以是插槽内容对象
!!! 如果是对象则是插槽
类型 说明 示例
type String | Component HTML 标签名 或 组件对象 'div', MyComponent
props Object 属性/事件对象 { class: 'red', onClick: fn }
children String | Array | VNode|slots 子节点(可嵌套) 'Text', [h('span'), ...] , default: () => vnode, // 对应 #default 插槽}
三、关键特性
1.动态组件支持
通过 type 参数直接渲染组件:
h(defineAsyncComponent(() => import('./AsyncComp.vue')), { prop: value })
2.事件绑定
使用 on 前缀声明事件:
h('button', {
onClick: () => console.log('Clicked!'),
onMouseenter: handleHover
}, '按钮')
3.插槽控制
通过 children 传递插槽内容
h(MyComponent, null, {
default: () => h('div', '默认插槽'),
})
h(Suspense, {
onResolve: () => { /* ... */ }
}, {
default: () => h(_component_dd_page, { class: 'dd-page' }),
fallback: () => h('div', 'Loading...')
})
是 Vue 3 引入的一个内置组件,用于管理异步依赖的加载状态,提供更优雅的异步组件和数据加载处理方案。
Suspense有两个插槽#default和#fallback,初始显示 fallback 内容
主要有4个回调
@resolve / onResolve:当所有异步依赖(组件/数据)加载完成时
@pending / onPending:当进入挂起状态(开始等待异步依赖)时
@fallback / onFallback:当开始显示备用内容(fallback)时
@errorCaptured / onErrorCaptured : 捕获异步错误
<template>
<Suspense @resolve="handleResolve"
@pending=“handlePeding”
@fallback=“handleFallback”>
<!-- 主内容区域(包含异步依赖) -->
<template #default>
<AsyncComponent />
</template>
<!-- 加载中状态 -->
<template #fallback>
<div class="loading-spinner">加载中...</div>
</template>
</Suspense>
</template>
<script setup>
import { defineAsyncComponent } from 'vue';
// 定义异步组件
const AsyncComponent = defineAsyncComponent(() =>
import('./components/AsyncComponent.vue')
);
</script>
app.directive
在 Vue.js 中,app.directive() 是用于注册全局自定义指令的核心 API,使开发者能够直接操作 DOM 元素实现特定功能
基础注册语法
const app = createApp(App);
// 注册指令(对象形式)
app.directive('focus', {
mounted(el) {
el.focus();
},
updated(){
}
});
// 注册指令(函数形式,等效于 mounted + updated)
app.directive('color', (el, binding) => {
el.style.color = binding.value;
});
模板使用:
<input v-focus>
<p v-color="'red'">红色文字</p>
指令生命周期钩子
钩子 触发时机 典型场景
created 绑定属性/事件应用前 初始化操作
beforeMount 元素插入 DOM 前 DOM 操作准备
mounted 元素插入 DOM 后(最常用) 自动聚焦、集成第三方库
beforeUpdate 组件 VNode 更新前 获取更新前状态
updated 组件 VNode 更新后 响应数据变化更新 DOM
beforeUnmount 元素卸载前 清理定时器/事件监听
unmounted 元素卸载后 最终清理
每个钩子接收相同参数:
{
mounted(el, binding, vnode) {
// el: 指令绑定的 DOM 元素
// binding: 指令信息对象
// vnode: Vue 编译生成的虚拟节点 } }
binding 对象关键属性
属性 说明 示例
value 指令绑定的值 v-my-dir="1 + 1" → 2
oldValue 更新前的值(仅 update 钩子) 数据变化前状态
arg 指令参数 v-my-dir:foo → 'foo'
modifiers 修饰符对象 v-my-dir.bar.baz → { bar: true, baz: true }
instance 组件实例 访问组件数据/方法
实战案例
- 权限控制指令
app.directive('permission', {
mounted(el, binding) {
const { hasPermission } = useAuthStore();
if (!hasPermission(binding.value)) {
el.parentNode?.removeChild(el);
}
}
});
<button v-permission="'admin'">管理员按钮</button>
这样仅管理员会展示这个按钮