likes
comments
collection
share

vue3书写风格,速度,混入等问题探讨

作者站长头像
站长
· 阅读数 19

初识Vue3.0

什么是 Vue?

Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。

本文探讨主题

Vue3与Vue2的对比探讨

  • 书写风格:选项式API组合式API以及 setup语法糖
  • ref 和 reactive 响应式和非响应式
  • 计算属性
  • 混入的方法重名问题
  • 速度:打包速度、构建速度、vite

一、书写风格

Vue提供两种不同的风格书写:选项式API组合式API

选项式API (Options API)示例

选项式Api是将datamethods包括后面的watchcomputed等分开管理

<template>
<div @click="changeMsg">{{msg}}</div>
</template>
<script>
export default  {
  data(){
    return {
     msg:'hello world'
    }
  },
  methods:{
    changeMsg(){
      this.msg = 'hello zte'
    }
  }
}
</script>

组合式API (Composition API)示例

组合式Api则是将相关逻辑放到了一起(类似于原生js开发),Vue3推荐语法

组合式 API通常会与 <script setup>搭配使用。这个 setup attribute 是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。比如<script setup> 中的导入和顶层变量/函数都能够在模板中直接使用。

<template>
  <div @click="changeMsg">{{ msg }}</div>
</template>

<script setup>
import { ref } from "vue";

const msg = ref('hello world')
const changeMsg = () => {
  msg.value = 'hello zte'
}
</script>

setup语法糖

setup语法糖则可以让变量方法不用再写return,后面的组件甚至是自定义指令也可以在我们的template中自动获得。

二、ref 和 reactive

选项式api中,data函数中的数据都具有响应式,页面会随着data中的数据变化而变化;

而组合式api中不存在data函数该如何呢?所以Vue3则引入了refreactive函数来使变量成为响应式的数据

响应式:Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM。

ref与reactive的区别

对比refreactive
返回数据类型RefImpl对象(也叫ref对象)Proxy对象
传入基本类型返回{value: 基本类型}禁止这么做
传入引用类型返回{value: Proxy对象}Proxy对象

ref

组合式 API 中,推荐使用 ref() 函数来声明响应式状态:

import { ref } from 'vue'

const count = ref(0)

ref()接收参数,并将其包裹在一个带有 .value 属性的 ref 对象中返回:

import { ref } from 'vue'
import type { Ref } from 'vue'

// 这里使用TS语言,更加严谨
const year: Ref<string | number> = ref('2023')

year.value = 2023 // 成功!

使用ref的时候在js中取值的时候需要加上.value

如果需要再组件中访问他们就需要用setup()包裹起来

export default {
  // `setup` 是一个特殊的钩子,专门用于组合式 API。
  setup() {
    const count = ref(0)

    // 将 ref 暴露给模板
    return {
      count
    }
  }
}
<div>{{ count }}</div>

为什么要使用 ref?

为什么我们需要使用带有 .value 的 ref,而不是普通的变量?

简单地讨论一下 Vue 的响应式系统是如何工作的。

当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。

这是通过一个基于依赖追踪的响应式系统实现的。当一个组件首次渲染时,Vue 会追踪在渲染过程中使用的每一个 ref。然后,当一个 ref 被修改时,它会触发追踪它的组件的一次重新渲染。

在标准的 JavaScript 中,检测普通变量的访问或修改是行不通的。

然而,我们可以通过 getter 和 setter 方法来拦截对象属性的 get 和 set 操作。

.value 属性给予了 Vue 一个机会来检测 ref 何时被访问或修改。

在其内部,Vue 在它的 getter 中执行追踪,在它的 setter 中执行触发。

从概念上讲,你可以将 ref 看作是一个像这样的

// 伪代码,不是真正的实现
const myRef = {
  _value: 0,
  get value() {
    track()
    return this._value
  },
  set value(newValue) {
    this._value = newValue
    trigger()
  }
}

reactive

使用 reactive() API。与将内部值包装在特殊对象中的 ref 不同,reactive() 将使对象本身具有响应性:

import { reactive } from 'vue'

const state = reactive({ count: 0 })

import { reactive } from 'vue'

interface Book {
  title: string
  year?: number
}

const book: Book = reactive({ title: 'Vue 3 指引' })

在模版中使用

<button @click="state.count++">
  {{ state.count }}
</button>

响应式对象是 JavaScript Proxy代理,其行为就和普通对象一样。

不同的是,Vue 能够拦截对响应式对象所有属性的访问和修改,以便进行依赖追踪和触发更新。

注意事项:

解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接。

总结:

reactive更推荐去定义复杂的数据类型

ref 更推荐定义基本类型

三、计算属性

模板中的表达式虽然方便,但也只能用来做简单的操作。

<script setup>
import { reactive, computed } from 'vue'

const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})

// 一个计算属性 ref
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})
</script>

<template>
  <p>Has published books:</p>
  <span>{{ publishedBooksMessage }}</span>
</template>

Vue 的计算属性会自动追踪响应式依赖。它会检测到 publishedBooksMessage 依赖于 author.books,所以当 author.books 改变时,任何依赖于 publishedBooksMessage 的绑定都会同时更新。

// TS
const double = computed<number>(() => {
  // 若返回值不是 number 类型则会报错
})

四、混入重命名解决方法

稍微说一下 vue3 项目中的 hooks 的使用,其实这个 hooks 呢是和 vue2 当中的 mixin 是类似的

混入,通过 mixin 混入来分发 vue 组件中的可复用功能。

一个混入对象可以包含任意组件选项。

当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

而 vue3 的 hooks 函数与 mixin 混入的区别,主要是 hooks 是函数。

特点:

  • vue3 中的 hooks 函数相当于 vue2 里面的 mixin 混入,不同在于 hooks 是函数。
  • vue3 中的 hooks 函数可以提高代码的复用性,能够在不同的组件当中都利用 hooks 函数。
  • hooks 函数可以与 mixin 连用,但是不建议。

Demo:一个小功能,就是获取页面的宽高值

实现方法:

<template>
  <h3>hooks</h3>

  <p>页面宽度: {{screen.width}}</p>
  <p>页面高度: {{screen.height}}</p>

  <el-button @click="getWH">获取页面的宽高</el-button>
</template>
<script setup>
  import { reactive } from 'vue'

  const screen = reactive({
    width: 0,
    height: 0
  })

  const getWH = () => {
    screen.width = document.documentElement.clientWidth
    screen.height = document.documentElement.clientHeight
  }

</script>
<style scoped>

</style>

如果这个功能在所有页面都需要使用,那就需要一边一边的复制粘贴。

使用hooks实现:

src 文件夹下创建一个 hooks 文件夹

vue3书写风格,速度,混入等问题探讨

在 hooks 文件夹下创建一个文件,名字就叫做 useScreenWh.js 文件

vue3书写风格,速度,混入等问题探讨

把获取可视化界面的代码放进这个 js 文件,然后导出去,给其他页面使用就可以了

import { reactive } from 'vue'

export default function () {  // 导出一个默认方法

  // 创建一个对象,保存宽度和高度值
  const screen = reactive({
    width: 0,
    height: 0
  })

  // 创建一个方法,获取可视化界面的宽度和高度值
  const getWH = () => {
    screen.width = document.documentElement.clientWidth
    screen.height = document.documentElement.clientHeight
  }

  return { screen, getWH }  // 方法返回宽高值
}

在需要使用 hooks 的文件引入就可以使用了

<template>
  <h3>hooks</h3>

  <p>页面宽度: {{screen.width}}</p>
  <p>页面高度: {{screen.height}}</p>

  <el-button @click="getWH">获取页面的宽高</el-button>

</template>
<script setup lang="ts">

  // 导入 hooks 
  import screenWH from '../hooks/useScreenWh.js'

  // 因为 screenWH 是一个导出的方法,所以需要调用一下子,然后顺便解构一下就可以在模板使用了。
  let { screen, getWH } = screenWH()

</script>
<style scoped>

</style>

五、速度研究

  • 更轻量的打包大小:Vue3采用了新的编译模板方式,将模板编译为更小且更高效的代码。新版本中,编译模板的过程更加智能化,并通过Tree-Shaking技术实现更好的代码摇树性能。
  • 支持模块化 :全面支持ES模块化,并且通过使用ES模块系统来组织和加载代码。
  • 静态组件:Vue3引入了一项名为静态组件提升的优化技术。在Vue2中,每次渲染组件时,都会创建一个新的响应式实例,这会消耗一定的内存和性能。
  • 全面支持TS

这就是vue3的基本使用,注意啊,是基本使用,vue3 相关的东西很多,这里只是简单的是用,剩下的你们慢慢看文档。

今天到这儿,打卡收工!

vue3书写风格,速度,混入等问题探讨

参考资料:

Vue3官方文档:v3.cn.vuejs.org/guide/intro…

TS官方文档:www.tslang.cn/docs/home.h…