Skip to content

VUE3 操作文档

一、vue2和vue3区别

(1) Vue2简介

Vue2是Options(选项式)风格 image-20240602174455289

缺陷: 1.Options 的 API,数据(data)方法(method)、**计算属性(computed)**是分散开的

2.若修改需求则需要分别修改 Options的各API,不方便维护和复用

(2) Vue3简介

Vue3是Composition的API(组合式式)

优势: 可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起。

二、Setup

(1) setup简介

vue2中script中包含method、data、computed等API,在vue3中用setup来代替。

(2) Vue3的script框架

js
 <script  setup lang='ts' name='VUE3'> //此处使用ts语言
     let age    =18 // 数据定义(类似于Vue2中的Data数据定义)    
     function changeName(){ //定义函数 (类似于Vue2中的Method函数方法)
         age+=1     
     }     
     //但触发该事件,页面数据不会发生改变 因为age 不是响应式    
     //由此介绍创建Vue3的基本响应式数据的API:"ref" 和 ""reactive""   
</script>

三、Ref和Reactive

(1) Ref (基本类型数据)

js
<template>         
 <div class="app">
   <h1>{{a}}</h1>  //渲染时则不需要 '.value' 
   <button @click="test">点击+1</button>
   </div>
</template>         
<script    setup lang="ts" name='app'>
   import {ref} from 'vue'    
   let a =  ref(11) //定义数据
   let car =ref([ //定义数组
     {id:'111',name:'a'},
     {id:'222',name:'b'},
   ])
   function test() {
       a.value+=1     //ref 的响应式数据要添加 '.value'才能对他进行修改
       console.log(car.value[0]) // 数组输出的格式
   }    
</script>

打印的数据样式为:image-20240602174455289

(2) Reactive (对象类型数据)

js
<template>
<div class="app">
    <h2>一辆{{car.name}}价值{{ car.price }}万</h2>
    <button    @click="changePrice">点击改变价格</button>
    </div>    
</template>    
<script setup lang="ts" name='app'>
    import {ref,reactive} from 'vue'
    let car = reactive({name:'迈凯伦Speedtail',price:1000})
    function changePrice(){
        car.price=1010 // reactive 不需要添加 ‘ .value ’     
        console.log(car);
    }    
</script>

打印的数据样式为:image-20240602174455289

注:reactive响应式数据为深层次的

js
<template>
  <div class="app">
    <h2>{{car.a.b.c}}</h2>
    <button @click="changePrice">点击改变价格</button>
  </div>
</template>
<script setup lang="ts" name='app'>
import {ref, reactive} from 'vue'
let car = reactive(
  {a:{ b:{c:11} } } //多重数据
)
function changePrice(){
  car.a.b.c=1010  //reactive可以修改深层次数据
  console.log(car);
}
</script>

(3) Ref 与 Reactive区别

1.当reactive对象在函数中被重新定义后,将不再是响应式对象,而是普通对象。

js
let car = reactive({brand:'奔驰;,price:100}) //响应式对
function changeCar(){
    car = {brand:'法拉利',price:1}  //变为普通对象
}

2.使用原则

  • 若需要一个基本类型的响应式数据,必须要使用ref。
  • 若需要一个响应式对象,层次不慎,ref,reactive都可以用。
  • 若需要一个响应式对象,且层级较深,推荐使用reactive。

四、toRefs和Reactive

1.toRefs(定义多个数据)

js
<template>
  <div class="app">
    <h2>{{name}}</h2>
    <h2>{{age}}</h2>
    <button @click="changePrice">点击改变价格</button>
  </div>
</template>
<script setup lang="ts" name='app'>
import {toRefs,reactive} from 'vue'
let person = reactive({
  name:'张三',
  age:18
})
let {name,age}= person  // 该命名后为普通数据
let {name,age}=toRefs(person) 
//此处的值来自于person,其中一个数值发生变化时,另外一个的数值会随之改变
// toRefs命名后为响应式数据,使用上述 可以简化数据的使用
function changePrice(){
name.value+='~' //修改后,person数据也会发生改变
}
</script>

注:toRefs是把reactive里面的定义的响应式对象的每一组单独的拿出来,再组成一个新的响应式对象.

2.toRef (定义单一)

使用方法:

js
let n1 =toRef(person,'age)
console.log(n1.value)

五、computed

computed: 计算属性有缓存效果,多处地方使用同一个参数时,不需要重复调用(为Ref定义的响应式数据)

method: 多处地方使用同一个参数时,需要重复调用

js
<template>
  <div class="app">
    姓名:<input type="text" v-model="firstName"> <br>
    名:<input type="text" v-model="lastName"> <br>
    全名:<span>{{fullName}}</span><br>
    全名:<span>{{fullName}}</span><br>
    全名:<span>{{fullName}}</span><br>
    全名:<span>{{fullName}}</span>
  </div>
</template>

<script setup lang="ts" name='app'>
import { computed, ref } from "vue"
let firstName =ref('zhang')
let lastName =ref('san')

// 这么定义的fullName是只读的,不可修改
// 不可修改(原因解释) : 输入框修改时  变化的是firstName的值  从而影响fullName发生改变 
let fullName = computed(() => {
  console.log(1); // 只会输出一次  具有缓存效果 当fullName发生改变时重新调用
  return firstName.value.slice(0,1).toUpperCase()+firstName.value.slice(1)+'1'+lastName.value
})

// 这么定义的fullName是可读可写的
 get(){
  return firstName.value.slice(0,1).toUpperCase()+firstName.value.slice(1)+'1'+lastName.value
 },
 set(){
    console.log(111);  
     //在此需要再结构赋值  拆分开后分别给给firstName 和 lastName赋值  
     //fullName才会发生改变(fullName是根据firstName,lastName计算来的)
 }
</script>

六、watch

  • 作用: 监视数据的变化 (和作用基本一致)

  • 特点: 只能监视以下四种数据

    1. ref 定义的数据
    2. reactive 定于的数据
    3. 函数返回值
    4. 一个包含上述内容的数值
  • 监视 watch(参数,回调函数=>{},配置对象) watch的第一个参数是:被监视的数据 watch的第二个参数是:监视的回调 watch的第三个参数是:配置对象(deep、immediate等等.....)

情况一

监视 ref 定义的【基本类型】数据:直接写数据名即可,监视的是其value值的改变。

js
<template>
  <div class="person">
    <h1>情况一:监视【ref】定义的【基本类型】数据</h1>
    <h2>当前求和为:{{sum}}</h2>
    <button @click="changeSum">点我sum+1</button>
  </div>
</template>

<script lang="ts" setup name="Person">
  import {ref,watch} from 'vue'
  // 数据
  let sum = ref(0)
  // 方法
  function changeSum(){
    sum.value += 1
  }
  // 监视,情况一:监视【ref】定义的【基本类型】数据
  const stopWatch = watch(sum,(newValue,oldValue)=>{
    console.log('sum变化了',newValue,oldValue)
    if(newValue >= 10){
      stopWatch()
    }
  })
</script>

情况二

监视 ref 定义的【对象类型】数据:直接写数据名,监视的是对象的 ,若想监视对象内部的数据,要手动开启深度监视。

js
<script lang="ts" setup name="Person">
  import {ref,watch} from 'vue'
  // 数据
  let person = ref({
    name:'张三',
    age:18
  })
  // 方法
  //若修改的是ref定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。
  function changeAge(){
    person.value.age += 1
  }
  //若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。
  function changePerson(){
    person.value = {name:'李四',age:90}
  }
  watch(person,(newValue,oldValue)=>{
    console.log('person变化了',newValue,oldValue)
  },{deep:true}) //添加deep可以开启深度监视
  
</script>

情况三

监视reactive定义的【对象类型】数据,且默认开启了深度监视。

js
<template>
<script lang="ts" setup name="Person">
  import {reactive,watch} from 'vue'
  // 数据
  let obj = reactive({
    a:{
      b:{
        c:666
      }
    }
  })
  // 方法
  function test(){
    obj.a.b.c = 888
  }

  // 监视,情况三:监视【reactive】定义的【对象类型】数据
  // 且默认是开启深度监视的。并且无法关闭
  watch(obj,(newValue,oldValue)=>{
    console.log('Obj变化了',newValue,oldValue)
  })
</script>

情况四

监视ref或reactive定义的【对象类型】数据中的某个属性,注意点如下:

js
<script lang="ts" setup name="Person">
  import {reactive,watch} from 'vue'

  // 数据
  let person = reactive({
    name:'张三',
    age:18,
    car:{
      c1:'奔驰',
      c2:'宝马'
    }
  })
  // 方法
  function changeName(){
    person.name += '~'
  }
  function changeAge(){
    person.age += 1
  }
  function changeC1(){
    person.car.c1 = '奥迪'
  }
  function changeC2(){
    person.car.c2 = '大众'
  }
  //如果不用()=>person.car的函数式  监视的不是地址值 则监视不到变化
  function changeCar(){ 
    person.car = {c1:'雅迪',c2:'爱玛'}
  }

  // 监视,情况四:监视响应式对象中的某个属性,且该属性是基本类型的,要写成函数式
  //函数式:getter函数(能返回值的函数)->  ()=>属性
  //例:watch(()=> person.name,(newValueoldValue)=>{})

  // 监视,情况四:监视响应式对象中的某个属性,且该属性是对象类型的,可以直接写,也能写函数,更推荐写函数
  watch(()=>person.car,(newValue,oldValue)=>{
    console.log('person.car变化了',newValue,oldValue)
  },{deep:true})
</script>

情况五

js
<script lang="ts" setup name="Person">
  import {reactive,watch} from 'vue'

  // 数据
  let person = reactive({
    name:'张三',
    age:18,
    car:{
      c1:'奔驰',
      c2:'宝马'
    }
  })
  // 方法
  function changeName(){
    person.name += '~'
  }
  function changeAge(){
    person.age += 1
  }
  function changeC1(){
    person.car.c1 = '奥迪'
  }
  function changeC2(){
    person.car.c2 = '大众'
  }
  function changeCar(){
    person.car = {c1:'雅迪',c2:'爱玛'}
  }

  // 监视,情况五:监视上述的多个数据 用数组形式填写到监视参数位置
  watch([()=>person.name,person.car],(newValue,oldValue)=>{
    console.log('person.car变化了',newValue,oldValue)
  },{deep:true})

</script>

七、watchEffect

  • 官网:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。
  • watch对比watchEffect
html
1.都能监听响应式数据的变化,不同的是监听数据变化的方式不同
2.watch:要明确指出监视的数据
3.watchEffect:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)。 //自动监视
  • 案例
js
<script lang="ts" setup name="Person">
  import {ref,watch,watchEffect} from 'vue'
  // 用watch实现,需要明确的指出要监视:temp、height
  watch([temp,height],(value)=>{
    // 从value中获取最新的temp值、height值
    const [newTemp,newHeight] = value
    // 室温达到50℃,或水位达到20cm,立刻联系服务器
    if(newTemp >= 50 || newHeight >= 20){
      console.log('联系服务器')
    }
  })

  // 用watchEffect实现,不用 (自动监视)
  const stopWtach = watchEffect(()=>{
    // 室温达到50℃,或水位达到20cm,立刻联系服务器
    if(temp.value >= 50 || height.value >= 20){
      console.log(document.getElementById('demo')?.innerText)
      console.log('联系服务器')
    }
    // 水温达到100,或水位达到50,取消监视
    if(temp.value === 100 || height.value === 50){
      console.log('清理了')
      stopWtach()
    }
  })
</script>

八、ref

  • 组件标签
js
<!-- 父组件App.vue -->
<template>
  <Person ref="ren"/>
  <button @click="test">测试</button>
</template>
 
<script lang="ts" setup name="App">
  import Person from './components/Person.vue'
  import {ref} from 'vue'
  let ren = ref()  //给打上标签
  function test(){// 获取子组件用defineExpose暴露的数据
    console.log(ren.value.name)
    console.log(ren.value.age)
  }
</script>
 
<!-- 子组件Person.vue中要使用defineExpose暴露内容 -->
<script lang="ts" setup name="Person">
  import {ref,defineExpose} from 'vue'
  // 数据
  let name = ref('张三')
  let age = ref(18)
  // 使用defineExpose将组件中的数据交给外部
  defineExpose({name,age})
</script>
  • 普通DOM标签
js
<template>
  <div class="person">
    <h1 ref="title1">尚硅谷</h1>
    <h2 ref="title2">前端</h2>
    <h3 ref="title3">Vue</h3>
    <input type="text" ref="inpt"> <br><br>
    <button @click="showLog">点我打印内容</button>
  </div>
</template>
 
<script lang="ts" setup name="Person">
  import {ref} from 'vue'
  let title1 = ref()
  let title2 = ref()
  let title3 = ref()
 
  function showLog(){
    // 通过id获取元素
    const t1 = document.getElementById('title1')
    // 打印内容
    console.log((t1 as HTMLElement).innerText)
    console.log((<HTMLElement>t1).innerText)
    console.log(t1?.innerText)
    // 通过ref获取元素
    console.log(title1.value)
    console.log(title2.value)
    console.log(title3.value)
  }
</script>

Last updated:

Author: Tt | 养老院高尚老头 | 张登哲