欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

迟到的 Vue3.0 与 Vite 的体验学习总结

程序员文章站 2022-03-21 11:10:31
尤大的 Vue3.0 已经发布有一阵子了,已经很成熟了。今天想起来,是时候该上手体验一波了。Vue3中文文档 - vuejsVue3.0 亮点Performance:性能更比Vue 2.0强;Tree shaking support:可以将无用模块“剪辑”,仅打包需要的;Composition API:组合式API;Fragment, Teleport, Suspense:“碎片”,Teleport 即 Protal 传送门,“悬念”;Better TypeScript support....

尤大的 Vue3.0 已经发布有一阵子了, 已经很成熟了。今天想起来,是时候该上手体验一波了。

Vue3中文文档 - vuejs

Vue3.0 亮点

  1. Performance:性能更比Vue 2.0强;
  2. Tree shaking support:可以将无用模块“剪辑”,仅打包需要的;
  3. Composition API:组合式API;
  4. Fragment, Teleport, Suspense:“碎片”,Teleport 即 Protal 传送门,“悬念”;
  5. Better TypeScript support:更优秀的Ts支持;
  6. Custom Renderer API:暴露了自定义渲染API;

Vue3.0 项目初始化

1. 安装 vue-cli 脚手架

$ npm install -g @vue/cli

安装成功后,使用 vue -V 命令,查看是否安装成功:

$ vue -V
@vue/cli 4.5.9

如果没有安装成功或者是还是2.0版本的,那么我们要将他升级到 3.0。
先将已有的 vue-cli 卸载,然后重新安装即可。

$ npm uninstall vue-cli -g

2. 创建 vue3.0 项目

$ vue create vue3-demo

在出现的命令交互窗口选择 Manually select features:

然后勾选:Router、Vuex、CSS Pre-processors 和 Linter / Formatter等内容。

回车后根据自己的习惯选择好,就开始创建项目。
迟到的 Vue3.0 与 Vite 的体验学习总结

选择vue版本:
迟到的 Vue3.0 与 Vite 的体验学习总结

安装完成之后就可以直接创建 vue3.0 的项目了,通过命令进行后续操作了。
通过下面两个命令就可以启动 vue3.0 的项目了。

 $ cd vue3-demo
 $ npm run serve

成功运行项目:
迟到的 Vue3.0 与 Vite 的体验学习总结
下面就开始干我们的正事了。。。


Vue3.0 新特性

1. 创建实例

在 Vue3 中每个 Vue 应用都是通过用 createApp 函数创建一个新的实例,不在通过 new 的方式进行创建:

Vue3创建实例的方式:

// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

createApp(App).use(store).use(router).mount('#app')

Vue2 通过函数式创建实例:、

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})

2. 创建路由

现在创建路由实例需要手动引入 createRouter 方法,创建 history 模式路由也需要手动引入 createWebHistory 方法,这达到 Tree-Shaking 的目的,即不会把所有的 api 都打包进来,只会打包你用到的 api,vue3 将都会使用这种形式。

import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

3. 响应式数据和事件绑定

Vue 3.0 中初始化状态通过 setup() 方法,定义状态需要调用 ref() 方法。
这就跟在 vue2 中有很大的不同,vue2 中我们是使用选项的方式来创建 datamethodswatchcomputed 的。

<template>
  <div>
      {{count}}
      {{str}}
      <button @click="add">add</button>
  </div>
</template>

<script>
import { ref } from 'vue';
export default {
    setup() {
        const count = ref(0); // 声明count,初始值为 0
        const str = ref('hello'); // 声明str,初始值为 'hello'
        const add = () => {	// 定义一个事件,用来更新count状态
            count.value ++;	// 更新count值的时候不能直接使用count++,而应使用 count.value++
        }
        return {
            count,
            str,
            add
        }
    },
}
</script>

4. 使用 reactive 声明响应式数据

使用 reactive 来一次声明多个变量

import { reactive } from 'vue'
export default {
  setup () {
    // 引入 reactive,同时定义多个变量
    const state = reactive({
      count: 0,
      str: 'hello'
    })
 
    // 现在访问变量,不能使用 .value 方式访问了
    const add = () => {
      // state.count.value++ // 错误
      state.count++
    }
 
    return {
      state,
      add
    }
  }
}

reactiveref 比较

  • reactive 是接收一个普通对象,返回该对象的响应式代理,它等同于 2.x 中的 Vue.observable()

    const obj = reactive({ count: 0 })
    // obj 此时是一个响应式的对象
    // 访问或修改,直接基于 obj.count
    
  • ref 也是接收一个参数并返回一个响应式且可改变的 ref 对象,一般参数是基础类型。
    如果传入的参数是一个对象,将会调用 reactive 方法进行深层响应转换。ref 对象拥有一个指向内部值的单一属性 .value,即当你要访问它的值时,需要 .value 拿到它的值。但是如果是在 setup 中返回且用到模板中时,在 {{}} 里不需要加 .value 访问,在返回时已经自动解套。

    setup() {
    	return {
    		count: ref(0), // 这里返回,在模板中无需 .value 访问值
    	}
    },
    

5. watchcomputed

在 Vue3 中使用监听器和计算属性,也需要手动引入,且 watchcomputed 都需要在 setup 中进行。

import { ref, watch, computed } from 'vue';
export default {
    setup() {
        const count = ref(0);
        const add = () => {
            count.value ++;
        }
        
        // 监听器 watch 同样是一个方法,它包含 2 个参数,2 个参数都是 function
        // 第一个参数是监听的值,count.value 表示当 count.value 发生变化就会触发监听器的回调函数,即第二个参数,第二个参数可以执行监听时候的回调
        watch(
	      () => count.value,  
	      (val, oldVal) => {
	        console.log(`new count: ${val},old count: ${oldVal}`);
	      }
	    );
	    
	    // 计算属性 computed 是一个方法,里面需要包含一个回调函数,当我们访问计算属性返回结果时,会自动获取回调函数的值:
	    const doubleCount = computed(() => {
	      return count.value * 2;
	    });
        return {
            count, 
            add,
            doubleCount
        }
    },
}

如果是 2 个以上的监听属性:

watch(
  [refA, () => refB.value],
  ([a, b], [prevA, prevB]) => {
    console.log(`a is: ${a}`)
    console.log(`b is: ${b}`)
  }
)

6. 获取路由信息

vue3.0 中使用 getCurrentInstance 方法获取当前组件实例,然后通过 ctx 属性获取当前上下文,ctx.$router 是路由实例,而 ctx.$router.currentRoute 就包含当前路由信息。

import { getCurrentInstance } from 'vue'
export default {
  setup () {
    const { ctx } = getCurrentInstance()
    console.log(ctx.$router.currentRoute.value)
  }
}

7. Vuex

在学习 Vue3 的 Vuex 4 之前,先来看一下 Vue2 的 Vuex 3:
可以发现创建 store 实例的方式改变了,vue2 中是使用 new 的方式进行创建的

export default new Vuex.Store({
   // ... 
})

看完 Vue2 的 Vuex 3,那么继续回到我们 Vue3 的使用。

  1. 定义 Vuex 状态

    state 中创建了一个状态,在 mutations 中添加修改该状态的方法,在actions 中提交 mutation 的方法,而不是直接变更状态。

    import { createStore } from 'vuex'
    
    export default createStore({
      state: {
        count: 0
      },
      mutations: {
        ADD(state) {
          state.count++;
        }
      },
      actions: {
        add({ commit }){
          commit('ADD')
        }
      },
      modules: {
      }
    })
    
    
  2. 更新 Vuex 状态

    方式一:
    在 xx.vue 页面中,通过计算属性使用 Vuex 状态;
    在具体事件中通过 store.dispatch 方法触发 Action。

    <template>
      <div>
        <div>state from vuex {{count}}</div>
        <button @click="add">add</button>
      </div>
    </template>
    
    <script>
    import { computed } from "vue";
    import { useStore } from 'vuex';  // 引入 useStore 方法返回 store 实例
    export default {
      setup() {
        const store = useStore()
        const count = computed(() => store.state.count)
        const add = () => {
          store.dispatch('add')
        }
        return {
          count,
          add,
        };
      },
    };
    </script>
    

    方式二:
    通过获取当前组件实例 ctx,使用 ctx.$store.commit 直接分发 mutations ,但是mutation有个限制:必须同步执行,而 Action 就不受约束,可以在 action 内部执行异步操作。

    <template>
      <div>
        <div>state from vuex {{count}}</div>
        <button @click="add">add</button>
      </div>
    </template>
    
    <script>
    import { computed, getCurrentInstance } from "vue";
    
    export default {
      setup() {
        const { ctx } = getCurrentInstance()
        const count = computed(() => ctx.$store.state.count)
        const add = () => {
          ctx.$store.commit('ADD')
        }
        return {
          count,
          add,
        };
      },
    };
    </script>
    

值得注意的新特性:

Vue 3 中需要关注的一些新功能包括:

非兼容的变更:

Global API

  • 全局 Vue API 已更改为使用应用程序实例
  • 全局和内部 API 已经被重构为可 tree-shakable

模板指令

  • 组件上 v-model 用法已更改
  • <template v-for> 和非 v-for 节点上 key 用法已更改
  • 在同一元素上使用的 v-ifv-for 优先级已更改
  • v-bind="object" 现在排序敏感
  • v-for 中的 ref 不再注册 ref 数组

组件

  • 只能使用普通函数创建功能组件
  • functional 属性在单文件组件 (SFC) <template>functional 组件选项被抛弃
  • 异步组件现在需要 defineAsyncComponent 方法来创建

渲染函数

  • 渲染函数 API 改变

  • $scopedSlots property 已删除,所有插槽都通过 $slots 作为函数暴露

  • 自定义指令 API 已更改为与组件生命周期一致

  • 一些转换 class 被重命名了:

    • v-enter -> v-enter-from
    • v-leave -> v-leave-from
  • 组件 watch 选项和实例方法 $watch 不再支持点分隔字符串路径,请改用计算函数作为参数

  • 在 Vue 2.x 中,应用根容器的 outerHTML 将替换为根组件模板 (如果根组件没有模板/渲染选项,则最终编译为模板)。VUE3.x 现在使用应用程序容器的 innerHTML

其他小改变

  • destroyed 生命周期选项被重命名为 unmounted
  • beforeDestroy 生命周期选项被重命名为 beforeUnmount
  • prop default 工厂函数不再有权访问 this 是上下文
  • 自定义指令 API 已更改为与组件生命周期一致
  • data 应始终声明为函数
  • 来自 mixindata 选项现在可简单地合并
  • attribute 强制策略已更改
  • 一些过渡 class 被重命名
  • 组建 watch 选项和实例方法 $watch 不再支持以点分隔的字符串路径。请改用计算属性函数作为参数。
  • <template> 没有特殊指令的标记 (v-if/else-if/elsev-forv-slot) 现在被视为普通元素,并 将生成原生的 元素,而不是渲染其内部内容。
  • 在 Vue 2.x 中,应用根容器的 outerHTML 将替换为根组件模板 (如果根组件没有模板/渲染选项,则最终编译为模板)。Vue 3.x 现在使用应用容器的 innerHTML,这意味着容器本身不再被视为模板的一部分。

以上内容如果想要详细了解,请移步至 v3 迁移指南


项目总结:

今天做一个小项目,想要使用Vue3 + Element-ui,发现Element-ui并不支持 Vue3中使用。查看源码发现,Vue3 在插件install函数的入参从Vue原型(类)改成了app(Vue的实例e),所以导致 element-ui中的Vue.prototype.*,这样的代码已经全部失效了。所以目前看来,element-ui是不能兼容Vue3的了。

但是 AntD2.0 测试版 支持 Vue 3.0 已发布。可以尝试一下。


Vue3.0 比较常见的新特性基本就是这些,后面还会不断学习补充,大家一起进步。加油!

本文地址:https://blog.csdn.net/XH_jing/article/details/111687106