Vue——vue3.0 第二篇

270 阅读3分钟

7.监听属性:watch函数

使用方法:

1.引入watch:

import {watch} from "vue"

2.使用watch

第一种:监听ref定义的响应式数据

// 让msg这个变量成为一个响应式数据
let msg=ref("karen")
let mn=ref("chongqi")
msg.value="jack"
// 监听msg、mn值的改变
//在vue3.0中可以监听多个数据
// 在vue3.0中监听函数可以写多个,注意必须要写是对那个变量进行监听的
watch([msg,mn],(newvalue,oldvalue)=>{
  // 当监听函数监听到msg值改变
  // 并且msg改变后的值为marry,就打印“值改变了”
  console.log(newvalue,oldvalue)
  if(newvalue[0]=="marry"){
    console.log("值改变了")
  }
})

// 点击事件触发,改变msg中的value值
let fn=function(){
  msg.value="marry"
}
let num =ref(0)

第二种:监听reactive定义的响应式数据

// 监听reactive所定义的一个响应式数据的全部属性

// 注意1:此处无法正确的获取oldvalue值(我们发现获取的值oldvalue=newvalue)

// 注意:并且强制开启了深度监视(此时的deep配置无效)
let obj=reactive({name:"颜淡",age:20,son:{age:1}})
let fn2=()=>{
  obj.son.age++
}
//监听obj
watch(obj,(newvalue,oldvalue)=>{
  console.log(newvalue,oldvalue)
})

案例:

image.png

8.生命周期函数

在vue3中,新增了一个setup生命周期函数,setup执行的时机是在beforeCreate生命函数之前执行,因此在这个函数中是不能通过this来获取实例的;同时为了命名的统一,将beforeDestroy改名为beforeUnmount,destroyed改名为unmounted,

vue3.0在vue2.0的基础上的更新:

vue2.0vue3.0
beforeCreatesetup
createdsetup
beforeMountbeforeMount
mountedmounted
beforeUpdatebeforeUpdate
updatedupdated
beforeDestroybeforeUnmount
destroyedunmounted
activated
deactivated
errorCaptured

vue3新增了生命周期钩子,我们可以通过在生命周期函数前加on来访问组件的生命周期

Composition API 形式的生命周期钩子

//Composition  API:组合式API
//如果要在steup函数中使用,就需要在生命周期函数前面加on
onBeforeMount        onMounted
onBeforeUpdate       onUpdated
onBeforeUnmount      onUnmounted
onErrorCaptured
onRenderTracked
onRenderTriggered

使用方法:

1.引入生命周期函数:

import {on+生命周期函数} from "vue"

2.使用生命周期函数:

on+生命周期函数(){
        代码;
    }

案例:

image.png

9.Teleport

Vue 鼓励我们通过将 UI 和相关行为封装到组件中来构建 UI。我们可以将它们嵌套在另一个内部,以构建一个组成应用程序 UI 的树。

然而,有时组件模板的一部分逻辑上属于该组件,而从技术角度来看,最好将模板的这一部分移动到 DOM 中 Vue app 之外的其他位置

具体使用场景:比如:模态弹窗

使用方法:

//to属性:放到指定位置
<div>
  <h1>{{msg}}</h1>
  <button @click="fn">按钮</button>
  
    <teleport to='body' >
          <h1>{{msg}}</h1>
      </teleport>
</div>

案例:

image.png

image.png

10.属性传值(父组件给子组件传值:)

第一种:继续使用vue2.0的语法

<script>
export default {
   props:["msg"],// props:{msg:String}, 
   setup(){}    
}
< /script>
<template>
  <div>
      {{msg}}
  </div>
</template>
    

    父组件:
    
   <script setup>
   import Box from "./Box.vue"
   let n="hello"
  </script>

<template>
  <div>
  <Box :msg="n"></Box>
  </div>
</template>
  

第二种:vue3组件内部组合式API setup中取属性值

<script>
export default {
//注册属性
   props:["msg","count"],// pops:{msg:String}, 
   setup(props,ctx){
   //props:父组件给子组件的属性传值
   //ctx:代表上下文对象,也就是vue提供的功能:emit、inject等
       let fn=()=>{console.log(props.msg,props.count)}//必须在组件中注册属性不然setup函数收不到数据
       return {fn}
   }    
}
< /script>
<template>
  <div>
     <p> {{msg}}</p>
      <button @click="fn">look</button>
  </div>
</template>
    

    父组件:
    <Box :msg="n" :count="200"></Box>

第三种:setup语法糖中获取属性值

<script setup>
    import {defineProps} from "./Box1.vue"
    //注意3.2之后不用引入可以直接使用
    let obj=defineProps(["msg","count"])
    let fn=()=>{console.log(obj.msg,obj.count)}         
}
< /script>
<template>
  <div>
     <p> {{obj.msg}}</p>
      <button @click="fn">look</button>
  </div>
</template>
    

    父组件:
    <Box :msg="n" :count="200"></Box>

11.自定义属性(子组件给父组件传值)

第一种:vue3.2之前的版本

  • 定义自定义事件

可以通过 emits 选项在组件上定义发出的事件

//父组件
<HomeView @my-event="fn" @my-submit="fn1"></HomeView>
​
//子组件
<template>
    <div @mouseenter="fm">
        <button @click="fn">点我触发mybtn组件内部的myclick事件</button>        
    </div>
</template><script>
    export default {
        emits:["myEvent","myclick"],
        methods:{
            fn(){
                this.$emit("myClick",200)
            },
            fm(){
                this.$emit("click",300)
            }
        }
        
    }
</script>
  • v-model 参数
//父组件
<HomeView v-model:title="bookTitle"></HomeView>
​
//子组件
//1.接收参数
props:["title"]
//2.定义事件
emits: ['update:title']
//3.触发事件
this.$emit("update:title","子组件传递给父组件的值")
  • 多个 v-model 绑定
//2.0这样写会有矛盾
<MyVmodel v-model="msg" v-model="msg2" v-model="msg3"></MyVmodel> 
        
//2.0应该这样写:
<MyVmodel 
    v-model="msg" 
    :msg2="msg2" @changemsg2="changemsg2" 
    :msg3="msg3" @changemsg3="changemsg3">
</MyVmodel>
js: 
changemsg2(arg){this.msg2=arg}
changemsg3(arg){this.msg3=arg}
        
        
//3.0
<MyVmodel v-model="msg" v-model:msg2="msg2" v-model:msg3="msg3"></MyVmodel> 
​
//父组件
<user-name
  v-model:msg1="msg1"
  v-model:msg2="msg2"
></user-name>
​
//子组件
//1.接收参数
props:["msg1","msg2"]
//2.定义事件
emits: ['update:msg1','update:msg2']
//3.触发事件
this.$emit('update:msg1',"子组件传递给父组件的值1")
this.$emit('update:msg2',"子组件传递给父组件的值2")

案例:

image.png

12. 状态驱动的动态 CSS

单文件组件的 <style> 标签可以通过 v-bind 这一 CSS 函数将 CSS 的值关联到动态的组件状态上

<template>
  <div class="box1">hello</div>
  <button @click="changcolor">修改box1的样式</button>
  <div class="box2">hello66666</div>
  <button @click="changother">修改box2的样式</button>
</template>

<script setup>

import { ref, reactive } from "vue"

//给这个变量定义成响应式数据
let color = ref("red")
let changcolor = () => {
  color.value = "blue"
}

let other = reactive({
  width: "200px",
  height: "100px"
})

let changother = () => {
  other.width = "400px"
}

</script>

<style lang="scss" scoped>
.box1 {
//绑定一个变量
  color: v-bind('color');
}

.box2 {
  background-color: yellow;
  width: v-bind('other.width');
  height: v-bind('other.height');
}
</style>

案例:

image.png

13.Suspense

  • 等待异步组件时渲染一些额外的内容,让应用有更好的用户体验

    <suspense> 组件有两个插槽。它们都只接收一个直接子节点。default 插槽里的节点会尽可能展示出来。如果不能,则展示 fallback 插槽里的节点。

    <template>
      <div class="fa">
        <h1>父组件HomeView</h1>
    ​
        <!-- <Helloworld></Helloworld> -->
        <suspense>
        //真正组件
          <template #default>
            <MyChild></MyChild>
          </template>
          //#:代表的是v-solt:
          //占位组件
          <template #fallback>
            <div>
              <h1> 正在加载中Loading...</h1>
            </div>
          </template>
        </suspense>
      </div>
    </template><script setup>
    //defineAsyncComponent:异步组件
    import { defineAsyncComponent } from "vue"
    // import Helloworld from "../components/HelloWorld.vue"  //静态引用let MyChild = defineAsyncComponent(() => import("../components/HelloWorld.vue")) //异步引入</script><style lang="scss" scoped>
    .fa {
      height: 300px;
      background-color: #ccc;
    }
    </style>