快速入门Vue3(上)

简介: 快速入门Vue3(上)

最近看了小满的vue3教学视频,官方文档,还有小余同学的笔记

也输出一份自己的总结,方便复习回顾。


Vue3的基本语法



Vue3新特性


1. API 风格


Vue2 是选项API(Options API),一个逻辑会散乱在文件不同位置(data、props、computed、watch、生命周期钩子等),导致代码的可读性变差。当需要修改某个逻辑时,需要上下来回跳转文件位置。


Vue3 组合式API(Composition API)则很好地解决了这个问题,可将同一逻辑的内容写到一起,增强了代码的可读性、内聚性,其还提供了较为完美的逻辑复用性方案。


Options API


使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 datamethodsmounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。


<script>
export default {
  // data() 返回的属性将会成为响应式的状态
  // 并且暴露在 `this` 上
  data() {
    return {
      count: 0
    }
  },
  // methods 是一些用来更改状态与触发更新的函数
  // 它们可以在模板中作为事件监听器绑定
  methods: {
    increment() {
      this.count++
    }
  },
  // 生命周期钩子会在组件生命周期的各个不同阶段被调用
  // 例如这个函数就会在组件挂载完成后被调用
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>


疑问1:为什么@click里面的increment不需要this.increment呢?methods里面的属性不是会暴露到实例上面吗,刚刚试了,@click="this.increment"

组合式 API (Composition API)


在单文件组件中,组合式 API 通常会与 <script setup> 搭配使用。这个 setup attribute 是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。

<script setup>
import { ref, onMounted } from 'vue'
// 响应式状态
const count = ref(0)
// 用来修改状态、触发更新的函数
function increment() {
  count.value++
}
// 生命周期钩子
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>


使用ref包裹之后会变成响应式的数据,我们之后也会介绍


2. 重写双向绑定

3. Vue3优化dom

4 .Vue3 Fragment

5. Vue3 Tree shaking


项目搭建


nvm

nvm安装


我们可以通过nvm来管理我们的node版本,方便切换不同的node版本 但是nvm有些坑,总结如下:

  1. nvm 路径不能有空格和中文
  2. 如果你已经有Node版本了,你需要把当前版本收录进去,或者直接卸载掉,用nvm重新安装一遍
  3. 用1.1.7版本,不要用1.1.9最新版本
  4. install版本失败,有可能需要给权限,cmd右键管理员启动即可


感谢b站的这位同学

image.png


nvm命令


# 查看已经安装的node版本
nvm list 
# 查看所有的node版本
nvm list available
# 安装node
nvm install 16.3.2(版本号)
# 切换node版本
nvm use 12.17.0


使用vite构建


npm init vue@latest

image.png


使用vue脚手架工具构建


使用vue脚手架会自动内置了vue-router, pinia,更适合vue的开发


npm init vue@latest

image.png


模板语法


文本插值


在script 声明一个变量可以直接在template 使用用法为 {{ 变量名称 }}


<template>
  <div class="about">
    <h1>{{ message }}</h1>
  </div>
</template>
<script setup lang="ts">
const message = "文本插值语法";
</script>

模板语法是可以编写条件运算的


<template>
  <div class="about">
    <h1>{{ message.length > 5 ? "一高" : "一快" }}</h1>
  </div>
</template>
<script setup lang="ts">
const message = "文本插值语法";
</script>


运算符也是可以支持的

<template>
  <div class="about">
    <h1>{{  message + "运算符" }}}</h1>
  </div>
</template>
<script setup lang="ts">
const message = "文本插值语法";
</script>


操作API 也是支持的


<template>
  <div class="about">
    <h1>{{ message.split("").reverse() }}</h1>
  </div>
</template>
<script setup lang="ts">
const message = "文本插值语法";
</script>


Attribute 绑定


任何 Vue 指令 (以 v- 开头的特殊 attribute) attribute 的值中

v-text


<span v-text="msg"></span>
<!-- 等同于 -->
<span>{{msg}}</span>

v-text 通过设置元素的 textContent 属性来工作,因此它将覆盖元素中所有现有的内容。同时设置v-text和标签中的内容会报错


<template>
  <div v-text="message">同时使用会报错</div>
</template>
<script setup lang="ts">
const message = "v-text用法";
</script>


v-html


<template>
  <div v-html="message"></div>
</template>
<script setup lang="ts">
const message = "<div>innnerHtml</div>";
</script>

v-if


v-if后面的值为真时,才会渲染,当条件改变时会触发过渡效果。

v-if

v-else-if

v-else


v-show


v-show 通过设置内联样式的 display CSS 属性来工作,当元素可见时将使用初始 display 值。当条件改变时,也会触发过渡效果。但是v-if会把整个节点变成一个注释节点,v-show的性能会更好一点


<template>
  <div v-show="bol">v-show为true显示</div>
</template>
<script setup lang="ts">
const bol = true;
</script>

v-on


v-on:可以简写为@

当用于普通元素,只能监听原生DOM事件。当用于自定义元素组件,则监听子组件触发的自定义事件


<!-- 方法处理函数 -->
<button v-on:click="doThis"></button>
<!-- 动态事件 -->
<button v-on:[event]="doThis"></button>
<!-- 内联声明 -->
// $event是一个event对象
<button v-on:click="doThat('hello', $event)"></button>
<!-- 缩写 -->
<button @click="doThis"></button>
<!-- 使用缩写的动态事件 -->
<button @[event]="doThis"></button>
<!-- 停止传播 -->
<button @click.stop="doThis"></button>
<!-- 阻止默认事件 -->
<button @click.prevent="doThis"></button>
<!-- 不带表达式地阻止默认事件 -->
<form @submit.prevent></form>
<!-- 链式调用修饰符 -->
<button @click.stop.prevent="doThis"></button>
<!-- 按键用于 keyAlias 修饰符-->
<input @keyup.enter="onEnter" />
<!-- 点击事件将最多触发一次 -->
<button v-on:click.once="doThis"></button>
<!-- 对象语法 -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

v-bind


动态的绑定一个或多个 attribute,也可以是组件的 prop。

缩写::


<!-- 绑定 attribute --> 
<img v-bind:src="imageSrc" />
<!-- 内联字符串拼接 -->
<img :src="'/path/to/images/' + fileName" />

v-model


在表单输入元素或组件上创建双向绑定。期望的绑定值类型:根据表单输入元素或组件输出的值而变化

  • 仅限:
  • <input>
  • <select>
  • <textarea>
  • components

v-for


<template>
  <div v-for="item in arr">{{ item }}</div>
</template>
<script setup lang="ts">

v-once


仅渲染元素的组件一次,并跳过之后的更新


<template>
  <button @click="increase"></button>
  <div>{{ val.count }}</div>
</template>
<script setup lang="ts">
import { ref } from "@vue/reactivity";
const val = ref({ count: 2 });
const increase = () => {
  console.log('你更新呀');
  val.value.count++;
};
</script>

当我们点击的时候,数值可以正常的更新,但是加了v-once之后,仅渲染元素和组件一次,并跳过之后的更新。再点击更新count的值元素不会进行更新


<template>
  <button @click="increase"></button>
  <div v-once>{{ val.count }}</div>
</template>
<script setup lang="ts">
import { ref } from "@vue/reactivity";
const val = ref({ count: 2 });
const increase = () => {
  console.log('你更新呀');
  val.value.count++;
};
</script>

v-memo


直接看小满的v-memo


ref全家桶


ref

Vue 提供了一个 ref() 方法来允许我们创建可以使用任何值类型的响应式 ref

ref接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。


const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
count.value++
console.log(count.value) // 1

如果ref是一个文本插值(即一个{{ }}符号)计算的最终值,它也被将解包,不需要再.value上取值:


{{ object.foo }}
{{ object.foo.value }}


ref 被传递给函数或是从一般对象上被解构时,不会丢失响应性:

好像自动解包哪些官方文档还没有看明白


ifRef


判断是不是一个ref对象


import { ref, Ref,isRef } from 'vue'
let message: Ref<string | number> = ref("我是message")
let notRef:number = 123
const changeMsg = () => {
  message.value = "change msg"
  console.log(isRef(message)); //true
  console.log(isRef(notRef)); //false
}


shallowRef


ref() 的浅层作用形式。


const state = shallowRef({ count: 1 })
// 不会触发更改
state.value.count = 2
// 会触发更改
state.value = { count: 2 }

特别注意

  • shallowRef只响应到.value,如果这个.value后面在跟值进行修改,就只能在控制台中看见值改变了,而没办法响应到页面中
  • 也就是创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的
  • ref不能跟shallowRef一起使用,不然shallowRef会被Ref影响,从而造成视图的更新(失去浅层次响应的作用)


triggerRef()


triggerRef()会强制更新我们收集的依赖


const shallow = shallowRef({
  greet: 'Hello, world'
})
shallow.value.greet = 'Hello, universe'
// 会强制更新
triggerRef(shallow)


customRef()


创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式。

customRef() 预期接收一个工厂函数作为参数,这个工厂函数接受 tracktrigger 两个函数作为参数,并返回一个带有 getset 方法的对象。

一般来说,track() 应该在 get() 方法中调用,而 trigger() 应该在 set() 中调用。然而事实上,你对何时调用、是否应该调用他们有完全的控制权。


<template>
  <div>customerRef: {{ obj }}</div>
  <button @click="change"></button>
</template>
<script setup lang="ts">
import { customRef, ref } from "vue";
const val = ref({ count: 2 });
const obj = MyRef('customerRef')
function change() {
  obj.value = 'customer 修改了'
}
function MyRef(value) {
  return customRef((tracker, trigger) => {
    return {
      get() {
        // 收集依赖
        tracker();
        // 收集完返回出去
        return value;
      },
      set(newVal) {
        // newVal是收到的新的值
        value = newVal;
        // 触发依赖更新
        trigger();
      },
    };
  });
}
</script>


认识Reactive全家桶


reactive


ref支持所有类型,reactive支持引用类型,Array,Object,Map,Set

ref取值是需要.value的,reactive取值的话不需要.value


reactive 基础用法

import { reactive } from 'vue'
let person = reactive({
   name:"小满"
})
person.name = "大满"

数组异步赋值问题


let person = reactive<number[]>([])
setTimeout(() => {
  person = [1, 2, 3]
  console.log(person);
},1000)

这样赋值页面是不会变化的因为会脱离响应式


解决方法


使用push方法


import { reactive } from 'vue'
let person = reactive<number[]>([])
setTimeout(() => {
  const arr = [1, 2, 3]
  person.push(...arr)
  console.log(person);
},1000)

包裹一层对象


type Person = {
  list?:Array<number>
}
let person = reactive<Person>({
   list:[]
})
setTimeout(() => {
  const arr = [1, 2, 3]
  person.list = arr;
  console.log(person);
},1000)

shallowReactive


只能对浅层的数据 如果是深层的数据只会改变值 不会改变视图,和shallowRef差不多


认识to全家桶


toRef

toRef只能修改响应式对象的值并且视图发生变化,非响应式的值可以修改,但是视图没有变化


<template>
  <div>
    <button @click="change">按钮</button>
    {{ state }}
  </div>
</template>
<script setup lang="ts">
import { reactive, toRef } from "vue";
// 必须加上reactive,才能是响应式,否则toRef没有作用
const obj = reactive({
  foo: 1,
  bar: 1,
});
// bar 转化为响应式对象,相当于解构
const state = toRef(obj, "bar");
const change = () => {
  state.value++;
  console.log(obj, state);
};
</script>


toRefs


可以帮我们批量创建ref对象主要是方便我们解构使用


import { reactive, toRefs } from 'vue'
const obj = reactive({
   foo: 1,
   bar: 1
})
let { foo, bar } = toRefs(obj)
foo.value++
console.log(foo, bar);


toRaw


将响应式对象转化为普通对象toRaw() 可以返回由 reactive()、readonly() 、shallowReactive() 或者 shallowReadonly() 创建的代理对应的原始对象。


computed计算属性


计算属性就是当依赖的属性的值发生变化的时候,才会触发它的更改,如果依赖值不变,使用的是缓存中的值


函数形式


import { computed, reactive, ref } from 'vue'
let price = ref(0)//$0
let m = computed<string>(()=>{
   return `$` + price.value
})
price.value = 500


对象形式


<template>
   <div>{{ mul }}</div>
   <div @click="mul = 100">click</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
let price = ref<number | string>(1)//$0
let mul = computed({
   get: () => {
      return price.value
   },
   set: (value) => {
      price.value = 'set' + value
   }
})
</script>
<style>
</style>


官方文档案例


<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>

不使用计算属性


<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>

如果不使用计算属性的话,需要我们在模板中写很长的一段代码,如果我们在多处地方使用的话,可不希望每个地方都写那么长,所以计算属性的作用就体现出来了

计算属性默认是只读的。当你尝试修改一个计算属性时,你会收到一个运行时警告。只在某些特殊场景中你可能才需要用到“可写”的属性,你可以通过同时提供 getter 和 setter 来创建


目录
相关文章
|
4月前
|
缓存 JavaScript PHP
斩获开发者口碑!SnowAdmin:基于 Vue3 的高颜值后台管理系统,3 步极速上手!
SnowAdmin 是一款基于 Vue3/TypeScript/Arco Design 的开源后台管理框架,以“清新优雅、开箱即用”为核心设计理念。提供角色权限精细化管理、多主题与暗黑模式切换、动态路由与页面缓存等功能,支持代码规范自动化校验及丰富组件库。通过模块化设计与前沿技术栈(Vite5/Pinia),显著提升开发效率,适合团队协作与长期维护。项目地址:[GitHub](https://github.com/WANG-Fan0912/SnowAdmin)。
702 5
|
1月前
|
缓存 前端开发 大数据
虚拟列表在Vue3中的具体应用场景有哪些?
虚拟列表在 Vue3 中通过仅渲染可视区域内容,显著提升大数据列表性能,适用于 ERP 表格、聊天界面、社交媒体、阅读器、日历及树形结构等场景,结合 `vue-virtual-scroller` 等工具可实现高效滚动与交互体验。
214 1
|
1月前
|
缓存 JavaScript UED
除了循环引用,Vue3还有哪些常见的性能优化技巧?
除了循环引用,Vue3还有哪些常见的性能优化技巧?
132 0
|
2月前
|
JavaScript
vue3循环引用自已实现
当渲染大量数据列表时,使用虚拟列表只渲染可视区域的内容,显著减少 DOM 节点数量。
84 0
|
4月前
|
JavaScript API 容器
Vue 3 中的 nextTick 使用详解与实战案例
Vue 3 中的 nextTick 使用详解与实战案例 在 Vue 3 的日常开发中,我们经常需要在数据变化后等待 DOM 更新完成再执行某些操作。此时,nextTick 就成了一个不可或缺的工具。本文将介绍 nextTick 的基本用法,并通过三个实战案例,展示它在表单验证、弹窗动画、自动聚焦等场景中的实际应用。
381 17
|
5月前
|
JavaScript 前端开发 算法
Vue 3 和 Vue 2 的区别及优点
Vue 3 和 Vue 2 的区别及优点
|
5月前
|
存储 JavaScript 前端开发
基于 ant-design-vue 和 Vue 3 封装的功能强大的表格组件
VTable 是一个基于 ant-design-vue 和 Vue 3 的多功能表格组件,支持列自定义、排序、本地化存储、行选择等功能。它继承了 Ant-Design-Vue Table 的所有特性并加以扩展,提供开箱即用的高性能体验。示例包括基础表格、可选择表格和自定义列渲染等。
373 6
|
4月前
|
JavaScript 前端开发 API
Vue 2 与 Vue 3 的区别:深度对比与迁移指南
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架,在过去的几年里,Vue 2 一直是前端开发中的重要工具。而 Vue 3 作为其升级版本,带来了许多显著的改进和新特性。在本文中,我们将深入比较 Vue 2 和 Vue 3 的主要区别,帮助开发者更好地理解这两个版本之间的变化,并提供迁移建议。 1. Vue 3 的新特性概述 Vue 3 引入了许多新特性,使得开发体验更加流畅、灵活。以下是 Vue 3 的一些关键改进: 1.1 Composition API Composition API 是 Vue 3 的核心新特性之一。它改变了 Vue 组件的代码结构,使得逻辑组
1459 0
|
6月前
|
JavaScript 前端开发 UED
vue2和vue3的响应式原理有何不同?
大家好,我是V哥。本文详细对比了Vue 2与Vue 3的响应式原理:Vue 2基于`Object.defineProperty()`,适合小型项目但存在性能瓶颈;Vue 3采用`Proxy`,大幅优化初始化、更新性能及内存占用,更高效稳定。此外,我建议前端开发者关注鸿蒙趋势,2025年将是国产化替代关键期,推荐《鸿蒙 HarmonyOS 开发之路》卷1助你入行。老项目用Vue 2?不妨升级到Vue 3,提升用户体验!关注V哥爱编程,全栈开发轻松上手。
410 2
|
6月前
|
JavaScript 前端开发 算法
高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图
mermaid是一款非常优秀的基于 JavaScript 的图表绘制工具,可渲染 Markdown 启发的文本定义以动态创建和修改图表。非常适合新手学习或者做一些弱交互且自定义要求不高的图表 除了流程图以外,mermaid还支持序列图、类图、状态图、实体关系图等图表可供探索。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~