vue3+vite+TypeScript 传值解析
在vue2系列中我们我们把状态都放到data返回的对象中,
父传子是通过给子组件添加属性和值,而子组件通过this.props来接收对应的值。
子传父则是通过this.$emit(‘方法名’,值)的方式去给父组件传值,而父组件通过给子组件注册对应事件来接收传递过来的实参。
首先vue3系列增加了setup函数,那么在写法上就容易造成一定困惑,下面通过小例子来说明:
<template>
<div>
<div>父组件</div>
<div>父传子counter的值:{{ counter }}</div>
<button @click="handleClick">点击加值</button>
<div>子组件传递过来deV的值:{{ deV }}</div>
<div>------以下为子组件------------</div>
<my-input @changeV="parentEvent" :counter="counter"></my-input>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import MyInput from "components/MyInput.vue";
export default defineComponent({
name: "home",
components: {
MyInput,
},
// data() {
// return {
// counter: 1,
// deV: "",
// };
// },
setup(p, t) {
const deV = ref("初始父值");
const counter = ref(1);
const parentEvent = (v: any) => {
deV.value = v.value;
};
const handleClick = () => {
counter.value++;
};
return { parentEvent, deV, handleClick, counter };
},
});
</script>
从代码中可以看出父传子方式上是一样的。需要注意的是当传过去的值是绑定ref时 在父组件parentEvent 方法中接收到的参数并不是传递过来的值,打印出来可以看到是一个对象,其中value,_rawValue和_value都能拿到这个值。其中_rawValue是未转换的原始值,而_value是转换后的值
<template>
<div>
<div>{{ title }}</div>
<input type="text" v-model="inputV" />
<button @click="changeV">点击改变子组件的值</button>
<div>{{ inputV }}</div>
<div>{{ count }}</div>
<div>父组件传过来的值:{{ counter }}</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, Ref } from "vue";
export default defineComponent({
name: "MyInput",
data() {
return {
title: "输入框子组件",
inputV: "",
};
},
props: {
counter: {
type: String,
required: false,
},
},
setup(props, context) {
const { emit } = context;
const inputV = ref("好");
const count = ref(0);
const changeV = () => {
count.value++;
emit("changeV", inputV);
};
return { changeV, count, inputV };
},
});
</script>
需要注意的是在setup函数中定义的函数和状态都要return出来。
//祖先组件
setup(p, t) {
const deV = ref("初始父值");
const counter = ref(1);
const other = reactive({ msg: counter });
provide("counter", readonly(counter));
provide("other", readonly(other));
const changeCounter = (v: any) => {
counter.value = v;
};
provide("changeCounter", changeCounter);
return { parentEvent, deV, handleClick, counter, other };
},
//子组件
<template>
<div>这是other组件,接收到的other对象中的msg值为:{{ getMsg.msg }}</div>
<div>这是接收到的counter值:{{ counter }}</div>
<button @click="handleDispatch">点击改公共值</button>
</template>
<script>
import { inject, ref } from "vue";
export default {
name: "other",
setup(p, c) {
const getMsg = inject("other", ref());
const counter = inject("counter", ref());
const changeCounter = inject("changeCounter");
// console.log(getMsg, counter, changeCounter, c);
const handleDispatch = () => {
changeCounter(5);
};
return { getMsg, counter, handleDispatch, changeCounter };
},
};
<script>
使用方法是:在祖先组件中使用provide(‘名称’,值),在需要使用的地方使用inject(‘名’)获取到传过来的值。如果需要在子孙组件中改值或者传值给祖先组件时,可以在祖先组件中传方法,通过方法获取到参数。
由于我也是这两天才开始写vue cli3所以有不完整或错误之处请见谅。