一、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
挂载阶段:onBeforeMount
、onMounted
更新阶段:onBeforeUpdate
、onUpdated
卸载阶段:onBeforeUnmount
、onUnmounted
需要先导入,再使用。使用时传入的是一个箭头函数。
import { onMounted } from 'vue'
onMounted(()=>{
...
})