标签: vue-2

  • 升级 Vue@2 项目到 Vue@3

    升级 Vue@2 项目到 Vue@3

    这篇主要是笔记。(我估计会是第一篇,因为只迁移了一个项目)

    1. 安装新包

    只记录必须重装的:

    npm i vue@3 vue-loader@16.0.0-beta.8 vue-router@4.0.0-beta.13 @vue/compiler-sfc

    2. 修改 Webpack 配置

    // v2
    const VueLoaderPlugin = require('vue-loader/lib/plugin');
    // v3
    const {VueLoaderPlugin} = require('vue-loader');
    
    // for DefinePlugin
    {
      plugins: [
        new DefinePlugin({
          __VUE_OPTIONS_API__: true,
          __VUE_PROD_DEVTOOLS__: false,
        }),
      ],
    }

    3. 修改入口文件

    没有 new Vue({}) 了,取而代之的是 Vue.createApp({}),后者还支持 tree-shaking。

    也不需要注册 Vue-router 了,直接 app.use(router) 就好。所以传统的入口文件就要修改为:

    // v2
    import Vue from 'vue';
    import VueRouter from 'vue-router';
    import App from './app';
    import 'bootstrap/dist/css/bootstrap.min.css';
    import '@/styl/index.styl';
    import router from './router';
    
    Vue.use(VueRouter);
    
    Vue.config.productionTip = false;
    
    new Vue({
      router,
      ...App,
    }).$mount('#app');
    
    // v3
    import {createApp} from 'vue';
    import App from './app';
    import 'bootstrap/dist/css/bootstrap.min.css';
    import '@/styl/index.styl';
    import router from './router';
    
    const app = createApp({
      ...App,
    });
    app.use(router);
    app.mount('#app');

    4. 修改 router

    Vue-router 的变化很大,建议大家好好看看 迁移手册。就我厂这个项目而言,主要是三个变化:

    1. 使用支持 tree-shaking 的函数 createRouter
    2. 修改 history: createWebHistory()
    3. 使用渲染函数 h 替换之前渲染方式
    // 加载方式
    import {h} from 'vue';
    import {
      createRouter,
      createWebHistory,
      createWebHashHistory,
      RouterView,
    } from 'vue-router';
    
    const routes = [
      {
        path: '/',
        name: 'home',
        component: {
          // vue-router v3
          render(createElement) {
            return createElement('router-view');
          }
    
          // vue-router v4
          render() {
            return h(RouterView);
          },
        },
        children: components,
      },
      // ....
    ];
    
    const router = createRouter({
      // vue-router v3
      mode: process.env.NODE_ENV === 'production' ? 'history' : 'hash',
      // vue-router v4
      history: process.env.NODE_ENV === 'production'
        ? createWebHistory()
        : createWebHashHistory(),
      scrollBehavior: (to) => {
        if (to.hash && !/^#/.test(to.hash)) {
          return {selector: to.hash};
        }
        // 这里有个小改动,x => left, y => top,简单提一下
        return {top: 0};
      },
      routes,
    });

    5. 自定义组件 v-model 修改

    • prop: value => modelValue
    • event: input => `update:modelValue`

    6. 一些小修改

    • beforeDestroy => beforeUnmount

    7. createApp 与 Application,与 Component

    v2 时,我们可以通过 new Vue({}) 初始化 Vue 实例。这个阶段,Vue 默认有一个全局对象 + 若干个实例,除了 local 的,就是全局的。

    v3 时,引入了 Application(应用)的概念,在全局和组件之间,增加了一个新的层级。这样一来,我们就可以在同一个 Web 产品中,使用 Application 来划分命令、组件、mixins 的范围。应该会增加代码的强壮程度(虽然我暂时还没用到)。

    不过,迁移代码的时候,也要注意。以前我们可能 new 一个实例,调用它的 methods;现在不行了,要这样做:

    // v2
    const ins = new Vue({});
    ins.doSomething();
    
    // v3
    const app = createApp({});
    const vm = app.mount('$el');
    vm.doSomething();

    8. 新的响应式 API

    v3 最大的变化就是重构了响应式实现,所以新增了不少响应式 API。同时,也会检查开发者的代码,如果发现不需要响应式的地方用到响应式对象,就会提示开发者,因为响应式会增加系统开销。

    这个时候可以用 markRawtoRaw 方法来修改对象,撤销之前附加在上面的响应式属性,提高访问效率。

    其它 API 还很多,后面慢慢更新吧。

    9. Devtool 和 SourceMap

    遗憾的是,目前 Vue Devtool 无法检测到 Vue。老项目的 SourceMap 也完全不生效,无法正常对 SFC 进行 debug。