Vue3详解

发布时间 2023-09-19 20:27:58作者: 剑断青丝ii

一、组合式api

1.setup选项

使用时机

![](https://img2023.cnblogs.com/blog/2901531/202309/2901531-20230918120443038-564643943.png)
<script>
export default {
  setup (){
    console.log(' setup')
  }
  beforeCreate(){
    console. log('beforeCreate")
  }
</script>

<template>
  <div>
  </div>
</template>

写代码的特点

<script>
export default {
  setup (){
    console.log(' setup')
    const message = 'this is message'
    const logMessage = () => {
      console.log(message)
    }
    return {
      message,
      logMessage
    }
  }
  beforeCreate(){
    console. log('beforeCreate")
  }
</script>

<template>
  <div>
    {{message}}
    <button @click="logMessage">log</button>
  </div>
</template>


setup中没有this

2. reactive和ref

reactive

作用:接受对象类型数据的参数传入并返回一个响应式的对象 响应式对象:如下方事例,但点击按钮时state中的count的值会发生变化,如果只是一个普通的对象,则按钮点击时不会发生变化
<script setup>
//1.导入函数
import {reactive} from 'vue'
//2.执行函数 传入一个对象类型的参数 变量接收
const state = reactive({
  count: 0
})
const setCount = () =>{
  state.count ++
}
</script>
<template>
  <button @click="setCount">{{ state.count}}</button>
</template>

ref

作用:接收简单类型或者对象类型的数据传入并返回一个响应式的对象
<script setup>
//1.导入函数
import {ref} from 'vue'
//2.执行函数 传入一个对象类型的参数 变量接收
const count = ref(0)//count就是一个响应式
const setCount = () =>{
//脚本区域修改ref产生的响应式对象数据,必须通过.value属性
  count.value ++
}
</script>
<template>
  <button @click="setCount">{{ count}}</button>
</template>

3. computed计算属性函数

计算属性基本思想和Vue2的完全一致,组合式API下的计算属性只是修改了写法

核心步骤:1.导入computed函数

2.执行函数 在回调参数中return基于响应式数据做计算的值,用变量接收

<script setup>
//1.导入函数
import {ref,computed} from 'vue'
const list =ref([1,2,3,4,5,6,7,8])
//2.执行函数return计算之后的值变量接收
const computedList = computed(()=>{
  return list.value.filter(item => item > 2)
})
</script>
<template>
  <div>原始的响应式数组--{{ list }}</div>
  <div>计算属性数组--{{ computedList }}</div>
</template>


设置3秒后自动修改list数组的值,计算属性的数组的值也会随之发生改变,说明ref生成返回的list数组是一个响应式数组

<script setup>
//1.导入函数
import {ref,computed} from 'vue'
const list =ref([1,2,3,4,5,6,7,8])
//2.执行函数return计算之后的值变量接收
const computedList = computed(()=>{
  return list.value.filter(item => item > 2)
})
setTimeout(()=>{
  list.value.push(9,10)
},3000)
</script>
<template>
  <div>原始的响应式数组--{{ list }}</div>
  <div>计算属性数组--{{ computedList }}</div>
</template>

4. watch函数

作用: 侦听一个或者多个数据的变化,数据变化时执行回调函数


俩个额外参数:1.immediate (立即执行) 2.deep (深度侦听

侦听单个数据的变化

<script setup>
//1.导入函数
import {ref} from 'vue'
//2.执行函数 传入一个对象类型的参数 变量接收
const count = ref(0)//count就是一个响应式
const setCount = () =>{
//脚本区域修改ref产生的响应式对象数据,必须通过.value属性
  count.value ++
}
//watch侦听单个数据源
//watch里面ref对象不需要加.value
watch(count,(newVal,oldVla)=>{
  console.log('count变化了',newVal,oldVla);
})
</script>
<template>
  <button @click="setCount">{{ count}}</button>
</template>

侦听多个数据的变化

<script setup>
//1.导入函数
import {ref} from 'vue'
//watch侦听多个个数据源
const  count = ref(0)
//脚本区域修改ref产生的响应式对象数据,必须通过.value属性
const setCount = () => count.value ++

const name = ref('cp')
const changeName = ()=>{
  name.value = 'tbh'
}
watch([count,name],([newCount,newName],[oldCount,oldName])=>{
  console.log('count的值或者name变化了',[newCount,newName],[oldCount,oldName]);
})
</script>
<template>
  <button @click="setCount">{{ count}}</button>
  <button @click="changeName">{{name}}</button>
</template>

immediate

说明:在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调
watch([count,name],([newCount,newName],[oldCount,oldName])=>{
  console.log('count的值或者name变化了',[newCount,newName],[oldCount,oldName]);
},{
  //watch立即执行
  immediate:true
})

deep

默认机制:通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep选项
<script setup>
//1.导入函数
import {ref} from 'vue'
const tbhname = ref({count:0})
watch(tbhname,()=>{
  console.log('count变化了');
})
</script>
<template>
  {{tbhname.count}}
  <button @click="changeStateCount">state中的count变化了</button>
</template>

修改state内部的count的值并没有触发watch的回掉,此时需要添加deep

<script setup>
//1.导入函数
import {ref} from 'vue'
const tbhname = ref({count:0})
watch(tbhname,()=>{
  console.log('count变化了');
},{
  deep:true
})
</script>
<template>
  {{tbhname.count}}
  <button @click="changeStateCount">state中的count变化了</button>
</template>


上述又回引出一个问题,如果tbhname中不止count一个属性的话,而我又只想监听但count的值变化才会触发tbhname的watch的回掉,其他值的改变并不会触发tbhname的watch的回掉
精确侦听对象的某个属性的方法如下:

<script setup>

import {ref, watch} from 'vue'

const tbhname = ref({
  count:0,
  age:20
})

const changeStateCount = ()=>{
  tbhname.value.count ++
}
const changeAge = ()=>{
  tbhname.value.age ++
}
//可以把第一个参数写成函数的写法,返回要监听的具体属性
watch(
  ()=>tbhname.value.count,
  ()=>{console.log('count变化了')}
)
</script>
<template>

  当前的count的值{{tbhname.count}}
  <button @click="changeStateCount">state中的count变化了</button><br>
  当前的age的值{{tbhname.age}}
  <button @click="changeAge">age改变</button>
</template>

以上精准侦听一个对象里的一个具体的属性的变化

5. 生命周期函数

基本使用

<script setup>
//生命周期函数的使用
import {onMounted} from 'vue'
onMounted(()=>{
  //自定义逻辑
  console.log('onMounted');
})

</script>
<template>

</template>

<style lang="less">

</style>

多次使用同一个生命周期函数

<script setup>
//生命周期函数的使用
import {onMounted} from 'vue'
onMounted(()=>{
  //自定义逻辑
  console.log('onMounted1');
})

onMounted(()=>{
  //自定义逻辑
  console.log('onMounted3');
})

onMounted(()=>{
  //自定义逻辑
  console.log('onMounted2');
})
</script>

6. 父子通信

父传子

父组件
<script setup>
//setup语法糖下局部组件无需注册直接可以使用
import textTa from './views/test/texTa'

</script>
<template>
  <div>
    <div>123</div>
    <textTa message="message"></textTa>
  </div>

</template>

子组件

<template>
  <div>父组件传入的值--{{message}}</div>
</template>

<script setup>

const Tbhprops = defineProps({
  message:String
})

//vue3里属性的值不能通过this来获取,只能通过如下方式获取
onMounted(()=>{
  console.log(Tbhprops.message);
})
</script>

子传父

子组件
<template>
  <div>父组件传入的值--{{message}}</div>
  <button @click="sendMsg">log</button>
</template>

<script setup>
import {onMounted} from 'vue'
const Tbhprops = defineProps({
  message:String
})

//传入数组的原因是,以后可能会定义多个事件,这里只有一个事件,因此数组里也只有一项
const emit = defineEmits(['get-message'])

const sendMsg = () =>{
  //触发自定义事件,并传递参数
  emit('get-message','this is son msg')
}
</script>

父组件

<script setup>
//setup语法糖下局部组件无需注册直接可以使用
import textTa from './views/test/texTa'

const getMessage = (msg)=>{
  console.log(msg);
}
</script>
<template>
  <div>
    <div>123</div>
    <textTa message="message" @get-message="getMessage"></textTa>
  </div>
</template>

7. 模版引用(ref)

基本使用

<script setup>
//setup语法糖下局部组件无需注册直接可以使用
import textTa from './views/test/texTa'
import {ref,onMounted} from 'vue'

//1.调用ref函数 -> ref对象
const comRef = ref(null)

//组件挂载完毕之后才能获取
onMounted(()=>{
  console.log(comRef.value);
})
</script>
<template>
  <div>
    <div>123</div>
    <textTa ref="comRef" message="message" @get-message="getMessage"></textTa>
  </div>

</template>

vue3的一个明显变化,通过ref拿到的元素并不包含元素内部的属性和方法,vue2中是包含的
默认情况下在