易笔记易笔记
首页
文章
分类
标签
首页
文章
分类
标签
AI 1GitHub 1开源 1游戏开发 1Claude Code 1工作流 1AI 编程 1效率工具 1LangChain 1Prompt 1Frontend 1cesium 2CSS 10iOS 1Safari 1css 1font 1typography 1ide 1Flexbox 1JS 3ThreeJS 23D 2PHP 1Vue 8Windows 4KMS 1Vue3 5uni-app 1Form 1Modal 1虚拟滚动 1Vue 3 1Composition API 1ref 1reactive 1美食 1空气炸锅 1烤鱼 1减脂餐 1JavaScript 1浏览器 API 1requestIdleCallback 1性能优化 2组件 1异步组件 1
还在手动加载全部组件?这招让 Vue 应用性能飙升 200%!

动态组件 + 异步组件,让你的 Vue 应用起飞

你是不是也遇到过这种情况:应用越做越大,页面打开越来越慢,用户开始抱怨卡顿?明明代码写得没问题,可性能就是上不去。

别担心,今天我要分享的 Vue 动态组件和异步组件技巧,能让你的应用性能瞬间起飞!看完本文,你将掌握 3 大核心技巧,轻松解决组件加载性能问题。

为什么你的 Vue 应用越来越慢?

先来看个真实场景:一个后台管理系统有几十个功能模块,如果一次性加载所有组件,首屏加载时间可能达到 5 秒以上!用户每次打开都要看着空白页面干等,体验极差。

分类: Vue3, 性能优化标签: Vue, Vue3, 组件, 异步组件, 性能优化
日期: 2/27/2026
Vue中$set原理详解

在Vue开发中,我们经常会遇到这样的问题:直接通过索引设置数组项或者给对象添加新属性时,视图并没有更新。这时我们就需要使用Vue提供的$set方法来解决这个问题。本文将深入探讨Vue中$set的实现原理。

为什么需要$set?

在Vue的响应式系统中,并不是所有数据变化都能被检测到。主要有以下两种情况:

1. 数组索引直接设置

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})

// 这种方式不会触发响应
vm.items[1] = 'x'
分类: Vue标签: Vue
日期: 9/26/2025
Vue中的nextTick原理详解

在Vue开发中,我们经常会遇到这样的场景:修改数据后立即操作DOM却发现DOM还未更新。这时我们就需要使用nextTick来解决这个问题。本文将深入探讨Vue中nextTick的实现原理。

什么是nextTick?

Vue在更新DOM时是异步执行的,只要侦听到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个watcher被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作是非常重要的。

然后,在下一个的事件循环"tick"中,Vue刷新队列并执行实际(已去重的)工作。Vue在内部对异步队列尝试使用原生的Promise.then、MutationObserver和setImmediate,如果执行环境不支持,则会采用setTimeout(fn, 0)代替。

分类: Vue标签: Vue
日期: 9/26/2025
虚拟滚动实践记录

在处理大量数据列表时,直接渲染所有数据会导致页面卡顿、内存占用过高。虚拟滚动是一种优化技术,只渲染可视区域内的元素,大大提升了性能。

为什么需要虚拟滚动?

  1. 性能问题:当列表数据量过大时,一次性渲染所有DOM元素会造成页面卡顿
  2. 内存占用:大量DOM节点会占用过多内存
  3. 用户体验:滚动不流畅,影响用户操作

vue-virtual-scroller

vue-virtual-scroller 是一个专门为Vue设计的虚拟滚动组件库,支持Vue 3。它提供了多种虚拟滚动组件:

分类: Vue3标签: Vue, 虚拟滚动
日期: 10/31/2025
安装lodash-es

pnpm install lodash-es --save
分类: Vue3标签: Vue, Vue3
日期: 7/6/2025
uni-app渲染后多一层嵌套问题

首先定义一个子组件my-component

问题

<template>
  <view class="dddd"></view>
</template>
分类: Vue3标签: Vue, Vue3, uni-app
日期: 9/22/2025
将弹窗组件封装成方法调用

import {
    createApp,
    h,
    ref,
    Component,
    ComponentInternalInstance
} from 'vue';
import AddDialog from './AddDialog.vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';

/**
 * 打开添加对话框
 * @param currentInstance - 当前组件实例
 * @param url - 请求接口地址
 * @param title - 对话框标题
 * @param config - 表单配置
 */
export const openAddDialog = (currentInstance: ComponentInternalInstance | null, url: string, title: string, config: any[]) => {
    // 创建用于挂载对话框的容器
    const container = document.createElement('div');
    document.body.appendChild(container);
    const parentApp = currentInstance?.appContext.app;

    // 定义对话框组件引用
    const dialogRef = ref<InstanceType<typeof AddDialog>>();

    // 创建 Vue 应用实例
    const app = createApp({
        setup() {
            // 渲染 AddDialog 组件
            return () => h(AddDialog, {
                ref: dialogRef,
                title,
                url,
                config,
                onClose: () => {
                    destroyDialog();
                }
            });
        }
    });

    if (parentApp) {
        // 继承全局属性
        Object.assign(app.config.globalProperties, parentApp.config.globalProperties);

        // 继承局部注册组件
        if (currentInstance) {
            // @ts-ignore 绕过 TypeScript 类型检查,获取内部组件定义
            const localComponents = currentInstance.type?.components || {};
            for (const [name, component] of Object.entries(localComponents)) {
                app.component(name, component as Component);
            }
        }
    }

    // 在应用实例中注册 Element Plus
    app.use(ElementPlus);

    // 定义销毁对话框的方法
    const destroyDialog = () => {
        app.unmount();
        document.body.removeChild(container);
    };

    // 挂载应用实例
    app.mount(container);

    // 打开对话框
    if (dialogRef.value) {
        dialogRef.value.open();
    }

    return {
        destroy: destroyDialog
    };
};

分类: Vue3标签: Vue, Vue3
日期: 7/4/2025
TypeScript基础

基本类型

1、布尔类型(boolean):
let flag:boolean=[false|true]

2、数字类型(number):
let num:number=12

3、字符串类型(string):
let str:string='hello world'

4、数组类型(array):
let array:number[]=[1,2]
let list: Array<number> = [1, 2, 3];

5、对象类型:
const obj:{  x:number;  y:number;} = { x: 1, y: 1 };
const obj : {[key:string] : string | number} = {name:'str',age:18};
const {id, name, price}:{  id: string;  name: string;  price: number} = product;

6、元组类型(tuple),元组类型是固定长度的数组,可以指定数组中每个元素的类型:
let tup:[string,number,boolean]=['we',21,false]

7、枚举类型(enum):
定义:enum 枚举变量名{ 枚举类名=枚举值,  枚举类名1=枚举值1}
	enum flag{ success=1, errorM=-1 }
使用:var  变量:枚举类型=枚举变量名.枚举名   ||  var 变量名=枚举变量名.枚举名
	var F:flag=flag.success    //var F=flag.success

例如: enum Weeks {Mon, Tue, Wed, Thu, Fri, Sat, Sun};
console.log(Weeks['Mon']); // => 0
console.log(Weeks[0]); // => 'Mon'
console.log(Weeks.Tue); // => 1

8、任意类型(any)可以赋值给任意变量:
let dom:any=document.getElementById('app')

9、未知(unknown):
let num:unknown

10、null和undefined:
let num:number|undefined|null
let num:number|undefined|nul

11、void类型(函数无返回值):
function fn():void{
  console.log('q'); 
}

12、never类型:never表示其他类型的(包括null和underfined)子类型,表示从未出现过的值,是一个隐含的类型。

注意:大写Boolean Number String 等,用于创建对应的包装对象,一般不用。
分类: Vue标签: Vue
日期: 9/26/2025