Vue3学习笔记——Day03: watcheEffect、ref属性、父传子和生命周期

一、watchEffect

对监视的几个数据有逻辑操作时,可用 watchEffect操作方便些。

 // watchEffect
     watchEffect(()=>{
        if(favo.value >= 10 || upvote.value >=5){
            console.log("报告服务器")
        }
     })

在这里插入图片描述

二、标签的ref属性

解决多个组件嵌套在一起后,可能因为命名重复而造成不必要的问题。
用法如下:

<script setup>
import { ref } from 'vue'

const p = ref()
</script>

<template>
  <p ref="p">hello</p>
</template>
  • 用在普通DOM标签上,获取的是DOM节点。
  • 用在组件标签上,获取的是组件实例对象。

1. 用在普通DOM标签上

比如: 在子组件中写的DOM操作,查看标题,由于命名冲突问题,打印的确实父组件的标题。

test.vue

<h2 id="myTitle">{{ titlePre }}</h2>

App.vue

<h2 id="myTitle">全栈开发</h2>

在这里插入图片描述
使用 标签的ref属性解决上述问题。
App.vue

<template>
    <h2 ref="myTitle" id="myTitle">全栈开发</h2>
    <button @click="operDom">DOM操作看标题</button>
    <div class="container">
        <test/>
    </div>
    
</template>
<script lang="ts" setup name="App">
    
    import test from './components/test.vue'
    import {ref} from 'vue'

    let myTitle = ref()
    function operDom(){
        console.log(myTitle.value)
    }
   
</script>

在子组件中同理。
在这里插入图片描述

2.用在组件标签上

得到是组件实例,等DOM节点加载完毕再看,直接看是undefined

<div class="container">
	<test ref="item"/>
</div>

但是此时看不到组件中的数据,被保护起来了。需要在组件中用defineExpose方法手动暴露组件中的数据。

    let {title, content,author} = toRefs(item) 

    defineExpose({
        title,content,author
    })

在这里插入图片描述

三、父传子

数据在父组件中,子组件要用到父组件中的数据。
在父组件的子组件标签上写属性,在子组件中用defineProps()方法接收。
在这里插入图片描述
在这里插入图片描述
App.vue

<template>
    <h2 id="myTitle">全栈开发</h2>

    <div class="container">
        <test v-for="item in items" :key="item.id" :rev="item" />
    </div>

</template>
<script lang="ts" setup name="App">

import { reactive } from 'vue';
import test from './components/test.vue'
let items = reactive([
    {
        id: "c001",
        imgUrl: "",
        title: "hello, vue3",
        content: "这是一个不错的开始。",
        author: {
            name: 'cwh',
            age: 18
        },
        label: '前端开发',
        favo: 12,
        upvote: 10

    },
    {
        id: "c002",
        imgUrl: "",
        title: "hello, typescript",
        content: "这是一个不错的开始。",
        author: {
            name: 'cwh',
            age: 18
        },
        label: '前端开发',
        favo: 12,
        upvote: 10

    },
    {
        id: "c003",
        imgUrl: "",
        title: "hello, python",
        content: "这是一个不错的开始。",
        author: {
            name: 'wang',
            age: 18
        },
        label: '后端开发',
        favo: 12,
        upvote: 10

    },
])

</script>
<style scoped>
.container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}

#myTitle {
    text-align: center;
}

button {
    margin: 10px;
}
</style>

test.vue

<template>
    <div class="outside">
        <div class="container">
            <div class="left"><img src="" alt="这是一张图片"></div>
            <div class="right">
                <h2 ref="myTitle">{{ titlePre }}</h2>
                <p>{{rev.content }}</p>
                <div class="other">
                    <div class="favo">收藏:{{rev.favo }}</div>
                    <div class="upvote">点赞:{{rev.upvote }}</div>
                </div>
                <p class="author">作者:{{rev.author.name }}</p>
            </div>
            <div class="label">{{ rev.label}}</div>
        </div>
    </div>



</template>

<script lang="ts" setup name="Person">
import { computed } from 'vue'

const props = defineProps(['rev'])
// console.log(props)
let title = props.rev.title
const titlePre = computed(
    {
        get() {
            
            return title.length > 12 ?title.slice(0, 12) + '...' : title
        },
        set(newValue) {
            title.value = newValue
        }

    }
)

</script>
<style scoped>
#myTitle {
    color: red;
}

.outside {
    margin-bottom: 10px;
}

.outside button {
    margin: 10px;
    margin-left: 0;

}

.operation {
    width: 500px;
}

.container {
    position: relative;
    display: flex;
    width: 500px;
    height: 200px;

}

.container .left {
    flex: 1;
    background-color: pink;
}

.container .right {
    flex: 3;
    background-color: skyblue;
    margin-left: 10px;
    padding: 10px;
}

.right h2 {
    text-align: center;
}

.label {
    color: green;
    position: absolute;
    top: 5px;
    right: 5px;
    font-size: 12px;
}

.author {
    position: absolute;
    right: 20px;
    bottom: 0px;
}

.other {
    display: flex;
    justify-content: right;
}

.upvote {
    margin-left: 10px;
}
</style>

对于defineProps()方法的对传值数据的限制类型与指定默认值是否传参等学完typescript再补充。

四、生命周期

从出现到消失。
vue3的生命周期分为4个阶段:
创建阶段:setup
挂载阶段:onBeforeMountonMounted
更新阶段:onBeforeUpdateonUpdated
卸载阶段:onBeforeUnmountonUnmounted

需要先导入,再使用。使用时传入的是一个箭头函数。

import { onMounted } from 'vue'
onMounted(()=>{
	...
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值