「这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战」。
ref操作DOM和组件实例
ref属性可以获取DOM或者组件实例。在vue2中,使用this.$refs.xxx来获取DOM或者组件实例。在vue3中不同。vue3中先通过ref声明响应式数据,然后返回给模板使用,模板再通过ref绑定数据。
<template>
<h1>ref的使用</h1>
<h3 ref="aa">我是一个h3的内容</h3>
</template>
<script>
import {onMounted, ref} from 'vue'
export default {
setup() {
const aa = ref(null)
onMounted(() =>{
console.log(aa.value);
})
return {
aa,
}
}
}
</script>
<style>
</style>
我们可以看下打印结果,获取到了DOM。
除了获取DOM,ref还可以获取组件实例,我们可以来调用组件实例中的方法。
创建MyForm.vue
<template>
<div>我是Form组件</div>
</template>
<script>
export default {
setup() {
const validate = () => {
console.log('表单校验');
}
return {
validate
}
}
}
</script>
<style>
</style>
然后在App.vue中注册引入。在setup函数中通过ref声明响应式数据,通过点击按钮调用MyForm.vue中的validate方法。
<template>
<h1>ref的使用</h1>
<h3 ref="aa">我是一个h3的内容</h3>
<button @click="fn">按钮</button>
<hr>
<MyForm ref="form"></MyForm>
</template>
<script>
import MyForm from './MyForm.vue'
import {onMounted, ref} from 'vue'
export default {
components: {
MyForm
},
setup() {
const aa = ref(null)
const form = ref(null)
onMounted(() =>{
console.log(aa.value);
})
const fn = () => {
form.value.validate()
}
return {
aa,
form,
fn
}
}
}
</script>
<style>
</style>
点击按钮,我们看到控制台打印出了结果。
废弃了过滤器
在vue3中废弃了过滤器。那么我们如果想使用过滤器的功能,该怎么办呢?官方建议我们使用方法调用或者计算属性。
<template>
<h1>ref的使用</h1>
<h3>{{ formatTime(now) }}</h3>
<h3>{{ formatTime(otherTime) }}</h3>
</template>
<script>
import moment from "moment";
export default {
setup() {
const now = new Date();
const otherTime = new Date("2022-2-15 12:00:00");
const formatTime = (value) => {
return moment(value).format("YYYY-MM-DD");
};
return {
now,
formatTime,
otherTime,
};
},
};
</script>
<style>
</style>
同样,我们可以看到结果。
父子组件通讯
父传子
跟vue2中一样,父传子我们通过props,但细节与vue2中不同。
<template>
<h1>我是一个父组件</h1>
<div>{{ money }} -- {{ car }}</div>
<hr />
<Son :money="money" :car="car"></Son>
</template>
<script>
import { ref } from "vue";
import Son from "./Son.vue";
export default {
components: {
Son,
},
setup() {
const money = ref(100);
const car = ref("玛莎拉蒂");
return {
money,
car,
};
},
};
</script>
<style>
</style>
在子组件中通过props接收。
<template>
<h1>我是子组件</h1>
<div>{{ money }} - {{ car }}</div>
</template>
<script>
export default {
props: {
money: {
type: Number,
default: 0,
},
car: {
type: String,
default: "",
},
}
};
</script>
<style>
</style>
如果我们想要使用父组件传过来的值呢,我们怎么在setup中获取到到父组件传递给子组件的值呢?注意:vue3中没有this。
setup函数接受两个参数,第一个参数是父组件传递给子组件的值props,第二个参数是上下文context,context.emit是用来子组件给父组件传值的,可以进行解构{emit}。子传父后续介绍。
setup(props,{emit}) {
console.log(props);
},
我们可以看到打印结果正是父组件传递给子组件的值。
我们使用计算属性对父组件传递给子组件的money进行处理。
setup(props,{emit}) {
console.log(props);
const allMoney = computed(() => {
return props.money + 1000
})
return {
allMoney
}
},
在模板中进行渲染。
<template>
<h1>我是子组件</h1>
<div>{{ money }} - {{ car }}</div>
<div>总共的钱{{allMoney}}</div>
</template>
子传父
如果我们在子组件中对父组件传递过来的值进行修改呢?在vue2中是可以在子组件中直接修改,但是不推荐,因为如果存在多个子组件修改值会造成数据混乱。而在vue3中,在子组件中直接是不可以的。
在子组件中,我们写一个按钮,并点击绑定buy事件,修改父组件传过来的值。
<button @click="buy">买手机</button>
在setup函数中定义buy方法,并返回。
const buy = () => {
props.money = props.money - 500;
};
我们可以看到运行结果,提示修改失败,该值是只读的。
那么正确做法是使用setup函数的第二个参数,并解构出emit。
setup(props, { emit }) {
console.log(props);
const allMoney = computed(() => {
return props.money + 1000;
});
const buy = () => {
// props.money = props.money - 500;
emit('buy', 500)
};
return {
allMoney,
buy,
};
},
在父组件中使用跟vue2一样。
<Son :money="money" :car="car" @buy="buy"></Son>
setup() {
const money = ref(100);
const car = ref("玛莎拉蒂");
const buy = (value) => {
money.value -= value;
};
return {
money,
car,
buy,
};
点击按钮,我们可以看到值的变化。
我们可以看到浏览器有个警告,提示我们增加emits选项。
我们在子组件中,增加这个emits选项,这样可以很方便地了解到在子组件中传递了父组件哪些东西。
emits: ['buy'],