Vue3 基础

 Vue3 在Vue2 的基础上做了许多的改进,主要有以下方面:1)性能提升,Vue3 对虚拟DOM进行了重写,引入了静态树和新的编译器。提高了渲染性能。2)响应式系统的改进,使用Proxy代理对象替代了Vue2中的Object.defineProperty。3)更好的TypeScript支持。

1 Vue3 基础

Vue的组件可以按两种不同的风格书写:选项式API和组合式API。组合式API通常会与<script setup>搭配使用(setup 是一个标识,告诉Vue需要在编译时进行一些处理)。

1.1 指令

指令时带有v-前缀的特殊attribute。例如v-bind 和 v-for等。指令参数是指指令标识冒号后面的表达式(或字符串)。v-bind:href, href 是指令参数,表示将值绑定到href属性上。指令参数有以下特点:

  1. 指令参数可以动态指定。
  2. 动态参数中的表达式的值应当是一个字符串,或者是null(表示显式移除该绑定)。且不能有引号。否则会有警告。
  3. 元素标签使用动态指令参数会有警告。
<script setup lang="ts">
import DirectiveView from "@/article/components/DirectiveView.vue";
import {ref} from "vue";

const directiveAtt = ref("title")
const aAtt = ref("href")
</script>

<template>
<div class="app-container">
  <div @click="directiveAtt === 'title'? directiveAtt = 'otherInfo' : directiveAtt = 'title'">更换指令</div>
  <directive-view :[directiveAtt]="'hello directive'"/>
<!--  原始标签有警告-->
  <a :[aAtt]="'www.baidu.com'">百度</a>
</div>
</template>

DirectiveView.vue

<script setup lang="ts">
import {defineProps} from "vue";

defineProps(["title","otherInfo"])
</script>

<template>
<div>title: {{ title }}</div>
<div>otherInfo: {{ otherInfo }}</div>
</template>

1.2 响应式基础

修改响应式状态时,DOM会被自动更新,当DOM更新不是同步的。Vue会在“next tick”更新周期中缓冲所有状态的修改。以确保不管你进行了多少次状态修改,每个组件都只会被更新一次。

nextTick() 是一个异步方法,用于等待下一次DOM更新刷新。

1.2.1 响应式状态

reactive 及 ref 都是用于声明响应式状态。reactive仅支持为对象声明响应状态,ref可以传入基本类型及对象(底层使用reactive)。

reactive

将响应对象的原始类型属性结构为本地变量,或者将该属性传递给函数时,将丢失响应性连接。

ref

  1. 作为响应式对象的属性被访问或修改时自动解包。
  2. 在模板渲染上下文中,只有顶级的ref属性才会被解包(文本插值时,如果属性是最终计算值,非顶级的ref属性也会被解包)。

表 reactive 及 ref 的特点

<script setup lang="ts">
import {nextTick, reactive, ref} from "vue";

let count = ref(0)
async function addCountHandler() {
  const titleElement = document.querySelector("#title")
  count.value++;
  console.log("before nextTick",titleElement.textContent) // 0
  await nextTick()
  console.log("nextTick",titleElement.textContent) // 1
}

const sumRef = ref(0)
let obj = reactive({sum:sumRef,name: 'js'})
sumRef.value = 1;
console.log(obj) // {sum:RefImpl,name: 'js'}
obj.sum = 2;
console.log(sumRef.value) // 2
let { sum } = obj
console.log(sum) // 2
sum = 3
console.log(sum) // 3
console.log(obj.sum) // 2
console.log(sumRef.value) // 2
let tempObj = ref({num: 1})

let tempObj2 = {num: ref(99)}

function changeSum(sumVal) {
  sumVal = 999
}
changeSum(obj.sum)
console.log(obj.sum) // 2
</script>

<template>
<div class="app-container">
  <div id="title" @click="addCountHandler">{{ count }}</div>
  <!--  会被解包-->
  <div>reactive解包:{{obj.sum + 1}} {{obj.sum}}</div>
  <!--  会被解包-->
  <div>ref解包:{{tempObj.num + 1}} {{ tempObj.num }}</div>
  <!--[object Object]1 99-->
  <div>ref为非顶级属性: {{ tempObj2.num + 1}} {{ tempObj2.num }}</div>
</div>
</template>

1.3 Class与Style绑定

class 与 style 的表达式处理字符串外也可以是对象或数组。

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

  const classObj = ref({title: true,red: true})
  const classObj2 = ref({border: true})
  const styleObj = {color: 'green','background-color': 'red'}
  const styleObj2 = {'font-weight': 'bold'}
  let tag = ref(true)
</script>

<template>
   <div :class="[classObj,tag ? classObj2 : '']">
      Hello Class
   </div>
  <div :style="[styleObj,styleObj2]">JS + TS + VUE</div>
</template>

<style scoped>
.title {
  font-size: 17px;
  font-weight: bold;
}
.red {
  color: red;
}
.border {
  border-bottom: solid 1px blue;
}
</style>

类与样式作用于组件时,如果组件有一个根标签,则类与样式都会被这个根标签基础。否则,需要在组件的标签中,指定需要继承的样式与类($attrs.class及 $attrs.style)。

<script setup lang="ts">
import StyleView from "@/article/components/StyleView.vue";
</script>

<template>
  <style-view style="color: red;font-weight: bold" class="title"/>
</template>

StyleView.vue

<template>
  <div>
    <div>Hello StyleView</div>
    <div :class="$attrs.class" :style="$attrs.style">TS</div>
  </div>
</template>

1.4 侦听器

1)watch 的第一个参数可以是不同形式的数据源:ref(包括计算属性)、一个响应式对象、一个getter函数、或多个数据源组成的数组。

2)当有多个数据源时,可以使用watchEffect函数,它可以自动跟踪回调的响应式依赖。

3)如果想在侦听器回调中更访问被Vue更新之后的所属组件的DOM,需要指明flush: ‘POST’选项。

<script setup lang="ts" xmlns="http://www.w3.org/1999/html">
import {ref, watch, watchEffect} from "vue";

  let count = ref(0)
  let tag = ref(false)

  watch([count,tag],([newCount,newTag],[oldCount,oldTag]) => {
     console.log("-----------watch")
     console.log("newCount:" + newCount + ";newTag:" + newTag + ";oldCount:" + oldCount + ";oldTag:" + oldTag)
     console.log("watch,element:" + document.querySelector("#count")?.textContent)
     console.log("-------------")
  })

  watchEffect(() => {
    console.log("-----------watchEffect")
    console.log("watchEffect, count:" + count.value + ",tag:" + tag.value)
    console.log("watchEffect,element:" + document.querySelector("#count")?.textContent)
    console.log("-------------")
  })

  watch(count,(newCount) => {
    console.log("-----------watchPost")
    console.log("newCount:" + newCount)
    console.log("watch post,element:" + document.querySelector("#count")?.textContent)
    console.log("-------------")
  },{flush: "post"})

</script>

<template>
  <div>
    <button @click="count++" id="count">{{count}}</button>
     <div/>
    <button @click="tag = !tag">{{tag}}</button>
  </div>
</template>
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值