vue 基础

1.vue 生命周期

Vue.js 是一个流行的前端 JavaScript 框架,它提供了一种用于构建用户界面的简单而灵活的方式。Vue 组件有一个生命周期,这是指组件从创建到销毁的一系列阶段,在这些阶段你可以执行特定的代码。

以下是 Vue 组件的生命周期钩子函数以及它们在组件生命周期中的顺序:

  1. beforeCreate:

    • 在实例初始化之后,但在数据观测(data observer)和 event/watcher 事件配置之前被调用。
    • 此时组件的 eldata 都未初始化。
  2. created:

    • 在实例创建完成后立即被调用。
    • 可以在这里进行数据初始化、Ajax 请求等操作。
  3. beforeMount:

    • 在挂载开始之前被调用,相关的 render 函数首次被调用。
  4. mounted:

    • 在 el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
    • 如果需要访问已经被编译的 DOM,或者执行依赖于 DOM 的操作,可以在这里进行。
  5. beforeUpdate:

    • 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
  6. updated:

    • 由于数据更改导致的虚拟 DOM 重新渲染和打补丁后调用。
    • 如果要在数据更改后等待 DOM 更新,可以使用 vm.$nextTick
  7. beforeDestroy:

    • 在实例销毁之前调用。此时实例仍然完全可用。
  8. destroyed:

    • 在实例销毁后调用。
    • 这里可以进行一些清理工作,比如清除定时器、解绑事件等。
  9. activated(仅用于 keep-alive 组件):

    • 被 keep-alive 缓存的组件激活时调用。
  10. deactivated(仅用于 keep-alive 组件):

  • 被 keep-alive 缓存的组件停用时调用。
  1. errorCaptured:
  • 当子孙组件抛出错误时,会调用该钩子。

这些生命周期钩子提供了一个机会来在组件不同阶段执行代码,使得你可以控制和响应组件的生命周期事件。

需要注意的是,在实际使用中,大多数情况下你只需要关心 created, mounted, updated, destroyed 这几个钩子。其他钩子通常用于一些特定的场景或者高级的用法。

2.vue 数据劫持

2.1 响应式

在 Vue 2.0 中,数据劫持是通过使用"响应式"系统来实现的,主要通过以下方式:

  1. Object.defineProperty 方法: Vue 2.0 使用Object.defineProperty来劫持对象属性的读取和修改操作。这个方法允许你在属性被访问或修改时执行自定义的代码。

  2. Observer 模式: Vue 2.0 的响应式系统通过一个 Observer 类来监视数据对象。这个类会递归地遍历数据对象的所有属性,然后使用Object.defineProperty来转化这些属性,使其具有响应式特性。

  3. 依赖追踪: 每个响应式属性都有一个依赖管理系统,它会追踪哪些 Watcher(观察者)依赖于该属性。当属性发生变化时,依赖于该属性的 Watcher 都会被通知到,从而触发相应的视图更新。

  4. Watcher: Watcher 是一个观察者对象,它负责将视图与数据关联起来。当数据发生变化时,Watcher 会通知视图更新。

总的来说,Vue 2.0 的数据劫持是通过 Observer、依赖追踪和 Watcher 三者协作来实现的。这使得当数据发生变化时,视图会自动更新,使得开发者可以更容易地构建响应式的用户界面。

2.2 具体实现

当你使用 Vue 2.0 创建一个 Vue 实例时,Vue 会在背后对数据对象进行响应式化处理。下面是 Vue 2.0 如何实现数据劫持的详细步骤:

  1. 数据对象创建: 你首先创建一个包含数据的对象,通常称为 Vue 实例的data选项。

    var vm = new Vue({
      data: {
        message: "Hello, Vue!",
      },
    });
    
  2. Observer 模式: Vue 内部使用一个叫做Observer的类来监测data选项中的数据。这个类会遍历data中的属性,并为每个属性添加gettersetter,以便在属性被访问和修改时执行相应的操作。

  3. 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;
        // 触发视图更新
      },
    });
    
  4. 依赖追踪: Vue 2.0 会在内部维护一个依赖追踪系统。每个响应式属性都有一个关联的依赖收集器,用来追踪依赖于该属性的所有 Watcher 对象。当属性被访问时,Watcher 会被添加到依赖收集器中。

  5. Watcher: Watcher 是一个观察者对象,它负责建立视图和数据之间的连接。每个 Watcher 都会关注一个特定的属性或表达式,当这个属性发生变化时,Watcher 会被通知到,然后触发视图的更新。

    // 简化的Watcher示例
    var watcher = new Watcher(vm, "message", function (newValue, oldValue) {
      // 当message属性变化时执行的回调函数
    });
    
  6. 视图更新: 当数据发生变化时,相关的 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/

Contributors: masecho