VUE 3.0初体验

时间:2020-9-22 作者:admin

前言

2020年9月19日凌晨,尤雨溪大大正式发布了3.0版本,代号:One Piece, 不要太刺激哦

Vue 从一开始就有一个简单的使命:成为一个任何人都能快速学会的平易近人的框架。随着我们用户群的增长,框架的范围也在不断扩大,以适应不断增长的需求。随着时间的推移,它演变成了我们所说的“渐进式框架”:一个可以逐步学习和采用的框架,同时随着用户应对越来越多的需求场景而提供持续的支持。

下面是3.0版本的一些特点

  1. 在 Vue 3 中,基于对象的 2.x API 基本没有变化,3.0 还引入了 [Composition API],旨在解决 Vue 在大规模应用中的使用痛点,实现了类似于 React 钩子的逻辑组成和重用,比 2.x 基于对象的 API 更灵活的代码组织模式和更可靠的类型推理。
  2. Vue 3 与 Vue 2 相比,在捆绑大小 (tree-shaking 时减少了 41%)、初始渲染 (快了 55%)、更新 (快了 133%) 和内存使用 (少了 54%) 方面都有[显著的性能提升]
  3. Vue 3 的代码库是用 TypeScript 编写的,具有自动生成,测试和捆绑的类型定义,因此它们始终是最新的。Composition API 可以很好地处理类型推断。Vetur 是我们的官方 VSCode 扩展,现在利用 Vue 3 改进的内部键入功能支持模板表达式和 props 类型检查。哦,如果您愿意,Vue 3 的打字完全支持 TSX。
  4. 为单文件组件 (SFC,即 `.vue` 文件) 提出了两个新特性:`<script setup>`和 `<style vars>`

接下来,搭建一个Vue 3.0项目练练手吧:

  • 基于 vue-cli 快速搭建 Vue 3.0 项目
  • Vue 3.0 基本特性体验
  • 集成 vue-router 和 vuex 4.0

Vue 3.0 项目初始化

第一步,安装vue-cli

npm install -g @vue/cli

注意,以下命令是错误的

npm install -g vue

npm  install -g vue-cli

安装成功后,我们可以使用vue命令,测试方法

$ vue -V
@vue/cli 4.3.1

第二步,初始化vue项目:

vue create vue-next-test

输入命令后,会出现命令行交互窗口,这里我们选择Manually select features:

Vue CLI v4.3.1
? Please pick a preset: 
  default (babel, eslint) 
❯ Manually select features 

随后,我们勾选: Router,vuex,css pre-processors 和 Linter / Formatter

Vue CLI v4.3.1
? Please pick a preset: Manually select features
? Check the features needed for your project: 
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◉ Router
 ◉ Vuex
 ◉ CSS Pre-processors
❯◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

注意:Vue 3.0 项目目前需要从 Vue 2.0 项目升级而来,所以为了直接升级到 Vue 3.0 全家桶,
我们需要在 Vue 项目创建过程中勾选 Router 和 Vuex,所以避免手动写初始化代码

升级vue 3.0项目

目前创建vue 3.0项目需要通过插件升级的方式来实现

vue-cli还没有直接支持,我们进入目录,并输入以下指令

cd vue-next-test
vue add vue-next

执行上述指令后,会自动安装vue-cli-plugin-vue-next插件,该插件会完成以下操作:

  • 安装 Vue 3.0 依赖
  • 更新 Vue 3.0 webpack loader 配置,使其能够支持 .vue 文件构建(这点非常重要)
  • 创建 Vue 3.0 的模板代码
  • 自动将代码中的 Vue Router 和 Vuex 升级到 4.0 版本,如果未安装则不会升级
  • 自动生成 Vue Router 和 Vuex 模板代码

完成上述操作后,该项目正式升级到vue 3.0,注意该插件还不能支持typescript,用typescript的同学还得再等等(还不太支持TS)

Vue 3.0基本特性体验

下面我们从项目开发的角度体验vue 3.0的开发流程

【创建路由】

项目开发中,我们通常需要创建新页面,然后添加路由配置,我们在 /src/views 目录下创建 Test.vue:

<template>
  <div class="test">
     <h1>vue3.0 初体验</h1>
     <p>少年你的头发可还好,???? 哈哈哈哈哈</p>
  </div>
</template>

<script>
 export default {
 }
</script>

<style lang="less" scoped>
.test {
  color: red;
}
</style>

之后在/src/router/index.js中创建路由配置

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

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  },
  {
    path: '/test',
    name: 'Test',
    component: () => import(/* webpackChunkName: "test" */ '../views/Test.vue')
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

初始化Vue Router 的过程与2.0的变化不大,只是之前采用构造函数的方式,这里改为使用createRouter来创建Vue Router实例

配置的方法基本一致,配置完成后我们还需要在App.vue中链接到Test.vue的路由

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
      <router-link to="/test">Test</router-link>
    </div>
    <router-view/>
  </div>
</template>

启动项目

npm run serve

状态和事件绑定

Vue中定义状态的方法为类似React Hooks的方法,下面我们在Test.vue中定义一个状态 count:

<template>
  <div class="test">
    <h1>test count: {{count}}</h1>
  </div>
</template>

<script>
  import { ref } from 'vue'

  export default {
    setup () {
        const count = ref(0)
        return {
            count
            }
        }
  }
</script>

Vue 3.0中初始化状态通过setup 方法

定义状态需要调用 ref方法。接下来我们定义一个事件,用来更新 count状态:

<template>
  <div class="test">
    <h1>test count: {{count}}</h1>
    <button @click="add">add</button>
  </div>
</template>

<script>
  import { ref } from 'vue'

  export default {
    setup () {
      const count = ref(0)
      const add = () => {
        count.value++
      }
      return {
        count,
        add
      }
    }
  }
</script>

这里的add方法不再需要定义在methods中,

但注意更新 count值的时候不能直接使用count++ ,而应使用count.value++,

更新代码后,点击按钮,count的值就会更新了

<template>
  <div class="test">
    <h1>test count: {{count}}</h1>
    <div>count * 2 = {{doubleCount}}</div>
    <button @click="add">add</button>
  </div>
</template>

<script>
  import { ref, computed, watch } from 'vue'

  export default {
    setup () {
      const count = ref(0)
      const add = () => {
        count.value++
      }
      watch(() => count.value, val => {
        console.log(`count is ${val}`)
      })
      const doubleCount = computed(() => count.value * 2)
      return {
        count,
        doubleCount,
        add
      }
    }
  }
</script>

计算属性couputed是一个方法,里面需要包含一个回调函数,当我们访问计算属性返回结果时,会自动获取回调函数的值

const doubleCount = computed(() => count.value * 2)

监听器watch同样是一个方法,它包含两个参数,两个参数都是function:

watch(() => count.value, 
  val => {
    console.log(`count is ${val}`)
  })

第一个参数是监听的值,count.value表示当count.value发生变化就会触发监听器的回调函数,而第二个参数,第二个参数可以执行监听时候的回调

如果是2个以上的监听属性,就是这样

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

获取路由

Vue 3.0通过 getCurrentInstance方法获取当前组件的实例,然后通过上下文属性ctx获取当前上下文,

ctx.$router是Vue Router实例,里面包含了currentRoute 可以获取到当前路由信息

<script>
  import { getCurrentInstance } from 'vue'

  export default {
    setup () {
      const { ctx } = getCurrentInstance()
      console.log(ctx.$router.currentRoute.value)
    }
  }
</script>

Vuex 集成

Vuex 的集成方法如下

定义Vuex状态

第一步,修改src/store/index.js文件:

import Vuex from 'vuex'

export default Vuex.createStore({
  state: {
    test: {
      a: 1
    }
  },
  mutations: {
    setTestA(state, value) {
      state.test.a = value
    }
  },
  actions: {
  },
  modules: {
  }
})

Vuex的语法和API基本没有改变,我们在state中创建了一个test.a状态,在mutations中添加了修改state.test.a状态的方法: setTestA

引用Vuex状态

第二步,在Test.vue中,通过计算属性使用Vuex状态:

<template>
  <div class="test">
    <h1>test count: {{count}}</h1>
    <div>count * 2 = {{doubleCount}}</div>
    <div>state from vuex {{a}}</div>
    <button @click="add">add</button>
  </div>
</template>

<script>
  import { ref, computed, watch, getCurrentInstance } from 'vue'

  export default {
    setup () {
      const count = ref(0)
      const add = () => {
        count.value++
      }
      watch(() => count.value, val => {
        console.log(`count is ${val}`)
      })
      const doubleCount = computed(() => count.value * 2)
      const { ctx } = getCurrentInstance()
      console.log(ctx.$router.currentRoute.value)
      const a = computed(() => ctx.$store.state.test.a)
      return {
        count,
        doubleCount,
        add,
        a
      }
    }
  }
</script>

这里我们通过计算属性来引用Vuex中的状态:

const a = computed(() => ctx.$store.state.test.a)

ctx 是上节中我们提到的当前组件实例

更新Vuex状态

更新Vuex状态任然使用commit方法,这点和2.0版本一致

<template>
  <div class="test">
    <h1>test count: {{count}}</h1>
    <div>count * 2 = {{doubleCount}}</div>
    <div>state from vuex {{a}}</div>
    <button @click="add">add</button>
    <button @click="update">update a</button>
  </div>
</template>

<script>
  import { ref, computed, watch, getCurrentInstance } from 'vue'

  export default {
    setup () {
      const count = ref(0)
      const add = () => {
        count.value++
      }
      watch(() => count.value, val => {
        console.log(`count is ${val}`)
      })
      const doubleCount = computed(() => count.value * 2)
      const { ctx } = getCurrentInstance()
      console.log(ctx.$router.currentRoute.value)
      const a = computed(() => ctx.$store.state.test.a)
      const update = () => {
        ctx.$store.commit('setTestA', count)
      }
      return {
        count,
        doubleCount,
        add,
        a,
        update
      }
    }
  }
</script>

这里我们点击update a按钮后,会触发update方法,此时会通过ctx.$store.commit调用setTestA方法,将count的值覆盖state.test.a的值

总的效果如下

最后,总结如下

vue 3.0都写在setup里,以前的所有数据状态都写在data里,

vue 2.0所有的方法都写在methods里,而现在可以根据功能模块把状态和方法划分在一起,更利于模块化,

不过这样对代码习惯和质量要求更高了,初学者用3.0可能会写的更混乱

貌似vue逐渐react化,存在即合理

好怕vuex会被provide和inject特性给替换掉

使用

了解有关 Vue 3.0 的更多信息,访问新文档网站。如果是 Vue 2.x 用户,访问迁移指南

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。