vue 基础
1.vue 生命周期
Vue.js 是一个流行的前端 JavaScript 框架,它提供了一种用于构建用户界面的简单而灵活的方式。Vue 组件有一个生命周期,这是指组件从创建到销毁的一系列阶段,在这些阶段你可以执行特定的代码。
以下是 Vue 组件的生命周期钩子函数以及它们在组件生命周期中的顺序:
beforeCreate:
- 在实例初始化之后,但在数据观测(data observer)和 event/watcher 事件配置之前被调用。
- 此时组件的
el
和data
都未初始化。
created:
- 在实例创建完成后立即被调用。
- 可以在这里进行数据初始化、Ajax 请求等操作。
beforeMount:
- 在挂载开始之前被调用,相关的 render 函数首次被调用。
mounted:
- 在 el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
- 如果需要访问已经被编译的 DOM,或者执行依赖于 DOM 的操作,可以在这里进行。
beforeUpdate:
- 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
updated:
- 由于数据更改导致的虚拟 DOM 重新渲染和打补丁后调用。
- 如果要在数据更改后等待 DOM 更新,可以使用
vm.$nextTick
。
beforeDestroy:
- 在实例销毁之前调用。此时实例仍然完全可用。
destroyed:
- 在实例销毁后调用。
- 这里可以进行一些清理工作,比如清除定时器、解绑事件等。
activated(仅用于 keep-alive 组件):
- 被 keep-alive 缓存的组件激活时调用。
deactivated(仅用于 keep-alive 组件):
- 被 keep-alive 缓存的组件停用时调用。
- errorCaptured:
- 当子孙组件抛出错误时,会调用该钩子。
这些生命周期钩子提供了一个机会来在组件不同阶段执行代码,使得你可以控制和响应组件的生命周期事件。
需要注意的是,在实际使用中,大多数情况下你只需要关心 created
, mounted
, updated
, destroyed
这几个钩子。其他钩子通常用于一些特定的场景或者高级的用法。
2.vue 数据劫持
2.1 响应式
在 Vue 2.0 中,数据劫持是通过使用"响应式"系统来实现的,主要通过以下方式:
Object.defineProperty 方法: Vue 2.0 使用
Object.defineProperty
来劫持对象属性的读取和修改操作。这个方法允许你在属性被访问或修改时执行自定义的代码。Observer 模式: Vue 2.0 的响应式系统通过一个 Observer 类来监视数据对象。这个类会递归地遍历数据对象的所有属性,然后使用
Object.defineProperty
来转化这些属性,使其具有响应式特性。依赖追踪: 每个响应式属性都有一个依赖管理系统,它会追踪哪些 Watcher(观察者)依赖于该属性。当属性发生变化时,依赖于该属性的 Watcher 都会被通知到,从而触发相应的视图更新。
Watcher: Watcher 是一个观察者对象,它负责将视图与数据关联起来。当数据发生变化时,Watcher 会通知视图更新。
总的来说,Vue 2.0 的数据劫持是通过 Observer、依赖追踪和 Watcher 三者协作来实现的。这使得当数据发生变化时,视图会自动更新,使得开发者可以更容易地构建响应式的用户界面。
2.2 具体实现
当你使用 Vue 2.0 创建一个 Vue 实例时,Vue 会在背后对数据对象进行响应式化处理。下面是 Vue 2.0 如何实现数据劫持的详细步骤:
数据对象创建: 你首先创建一个包含数据的对象,通常称为 Vue 实例的
data
选项。var vm = new Vue({ data: { message: "Hello, Vue!", }, });
Observer 模式: Vue 内部使用一个叫做
Observer
的类来监测data
选项中的数据。这个类会遍历data
中的属性,并为每个属性添加getter
和setter
,以便在属性被访问和修改时执行相应的操作。Object.defineProperty: 通过
Object.defineProperty
,Vue 能够监听属性的变化。这意味着当你尝试读取或修改data
选项中的属性时,Vue 能够捕捉到这些操作,并触发相应的事件。var data = { message: "Hello, Vue!" }; // 使用Object.defineProperty将message属性转化为响应式 Object.defineProperty(data, "message", { get: function () { // 当属性被访问时执行的代码 return value; }, set: function (newValue) { // 当属性被修改时执行的代码 value = newValue; // 触发视图更新 }, });
依赖追踪: Vue 2.0 会在内部维护一个依赖追踪系统。每个响应式属性都有一个关联的依赖收集器,用来追踪依赖于该属性的所有 Watcher 对象。当属性被访问时,Watcher 会被添加到依赖收集器中。
Watcher: Watcher 是一个观察者对象,它负责建立视图和数据之间的连接。每个 Watcher 都会关注一个特定的属性或表达式,当这个属性发生变化时,Watcher 会被通知到,然后触发视图的更新。
// 简化的Watcher示例 var watcher = new Watcher(vm, "message", function (newValue, oldValue) { // 当message属性变化时执行的回调函数 });
视图更新: 当数据发生变化时,相关的 Watcher 会被通知到,它们会触发视图的重新渲染,从而确保视图与数据保持同步。
这些步骤使得 Vue 2.0 能够自动追踪数据的变化并实时更新相关视图,从而实现了数据劫持和响应式的功能。这个机制使得开发者能够更方便地构建交互性强、动态更新的用户界面。
3.vite 配置
3.1 vite 基本配置
当你创建一个 Vite 项目时,Vite 会自动生成一个默认的配置文件vite.config.js
。下面是一个更详细的 Vite 配置示例,其中包括了各种常见的配置选项和插件:
import { defineConfig } from "vite";
import Vue from "@vitejs/plugin-vue";
export default defineConfig({
// 项目的根目录
root: "./",
// 项目的输出目录
build: {
outDir: "dist",
},
// 本地开发服务器配置
server: {
port: 3000, // 本地服务器端口
open: true, // 启动时自动打开浏览器
},
// 预处理器配置,这里使用了Vue,你可以根据需要添加其他预处理器
plugins: [Vue()],
// 静态资源的公共路径(可选)
base: "/my-app/",
// 配置别名,用于导入模块时简化路径
resolve: {
alias: {
"@": "/src",
},
},
// CSS配置
css: {
preprocessorOptions: {
scss: {
// 在这里添加你的SCSS配置
},
},
},
// 全局变量配置,用于在代码中访问全局变量
define: {
"process.env" : process.env,
},
// 构建时是否生成sourcemap(开发环境建议开启,生产环境建议关闭)
build: {
sourcemap: true,
},
// Rollup配置,用于更高级的构建配置(可选)
// rollupOptions: {},
// 使用VLS(Vetur Language Server)插件提供更好的Vue支持(可选)
// optimizeDeps: {
// include: ['vue'],
// },
});
这是一个典型的 Vite 配置文件示例,你可以根据项目的需要进行调整和扩展。确保根据你的项目需求安装和配置适当的插件,例如在这里我们使用了 Vue 插件。如果你使用其他框架或库,还需要相应地配置和安装相关插件。
请注意,上面的示例中包含了一些常用的配置选项,但 Vite 支持许多其他配置选项,可以根据项目的需要进行进一步的定制化。在 Vite 的官方文档中可以找到更多关于配置选项的详细信息:https://vitejs.dev/config/
3.2 rollup 配置
当你需要更详细的 Rollup 配置时,你可以使用rollupOptions
对象来自定义 Rollup 的行为。以下是一个更详细的示例,展示了一些常见的 Rollup 配置选项:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
// 通常情况下,你会在这里配置输入文件
input: "src/main.js",
// 用于输出配置
output: {
// 输出目录
dir: "dist",
// 输出格式
format: "es", // 可选的值包括 'es', 'cjs', 'umd', 'iife' 等
// 输出文件的文件名,可以使用占位符
// [name] - 输入文件名
// [hash] - 构建哈希值
// [format] - 输出格式
// [ext] - 文件扩展名
entryFileNames: "[name]-[hash].[format].js",
chunkFileNames: "[name]-[hash].[format].js",
},
// 自定义Rollup插件
plugins: [
// 示例:添加一个自定义Rollup插件
myCustomPlugin(),
],
// 外部依赖,不会被打包
external: ["axios", "lodash"],
// Rollup的其他配置选项
treeshake: true, // 是否启用tree-shaking
inlineDynamicImports: true, // 将动态导入的模块内联
},
},
});
// 自定义Rollup插件示例
function myCustomPlugin() {
return {
name: "my-custom-plugin",
// 插件的处理逻辑
transform(code, id) {
if (id.endsWith(".js")) {
// 在这里进行代码转换或其他操作
const transformedCode = modifyCode(code);
return {
code: transformedCode,
map: null, // 可选的sourcemap
};
}
},
};
}
function modifyCode(code) {
// 在这里进行代码修改
return code;
}
在这个示例中,我们定义了一个更详细的 Rollup 配置:
input
用于指定入口文件。output
对象包含了输出的配置,你可以指定输出目录、输出格式以及文件名的模板。external
数组列出了那些不需要被打包的外部依赖。treeshake
用于启用或禁用 tree-shaking。inlineDynamicImports
用于将动态导入的模块内联到主文件中。plugins
数组包含自定义 Rollup 插件的配置,你可以根据需要添加更多的自定义插件。
自定义插件的示例代码也包括在内,以展示如何编写一个简单的自定义 Rollup 插件来修改代码。
根据你的项目需求,你可以根据 Rollup 的官方文档和 Vite 的文档来进一步定制和扩展配置:https://rollupjs.org/guide/en/ 和 https://vitejs.dev/config/