1.组件的v-model
image.pngApp.vue
<template>
<!-- <input v-model="message"> -->
<!-- <input :value="message" @input="message=$event.target.value"> -->
<!-- 组件上使用v-model -->
<hy-input v-model="message"></hy-input>
<!-- 相当于帮你绑定一个熟悉叫做modelValue这个属性 -->
<!-- <hy-input
:modelValue="message"
@update:model-value="message = $event"
></hy-input> -->
</template>
<script>
import HyInput from "./HyInput.vue";
export default {
components: {
HyInput,
},
data() {
return {
message: "hello world",
};
},
};
</script>
<style></style>
HyInput.vue
<template>
<div>
<button @click="btnClick">HyInput按钮</button>
<h2>HyInput的message:{{ modelValue }}</h2>
</div>
</template>
<script>
export default {
props: {
modelValue: String,
},
emits: ["update:modelValue"],
methods: {
btnClick() {
this.$emit("update:modelValue", "testtest");
},
},
};
</script>
<style lang="scss" scoped></style>
2. 实现v-model
方式一:
image.png
<template>
<div>
<input :value="modelValue" @input="btnClick" />
</div>
</template>
<script>
export default {
props: {
modelValue: String,
},
emits: ["update:modelValue"],
methods: {
btnClick(event) {
this.$emit("update:modelValue", event.target.value);
},
},
};
</script>
<style lang="scss" scoped></style>
方式二:
image.png
<template>
<div>
<!--
绑定 modelValue 是不对的,因为props是单向数据流,子不能修改父的值,只能emit发送过去
<input v-model="modelValue" />
-->
<input v-model="value" />
</div>
</template>
<script>
export default {
props: {
modelValue: String,
},
computed: {
value: {
set(newValue) {
this.$emit("update:modelValue", newValue);
},
get() {
return this.modelValue;
},
},
},
};
</script>
<style lang="scss" scoped></style>
3. 绑定多个属性
image.pngApp.vue
<template>
<!-- 绑定两个v-model -->
<!-- 组件是可以传参数的,在冒号后面
这时候子组件里面就多了一个props属性title,
也多了一个emits事件"update:title""
-->
<hy-input v-model="message" v-model:title="title"></hy-input>
<h2>{{ message }}</h2>
<h2>{{ title }}</h2>
</template>
<script>
import HyInput from "./HyInput.vue";
export default {
components: {
HyInput,
},
data() {
return {
message: "hello world",
title: "hahahha",
};
},
};
</script>
<style></style>
HyInput.vue
<template>
<div>
<input v-model="value" />
<input v-model="titleData" />
</div>
</template>
<script>
export default {
props: {
modelValue: String,
title: String,
},
emits: ["update:modelValue", "update:title"],
computed: {
value: {
set(newValue) {
this.$emit("update:modelValue", newValue);
},
get() {
return this.modelValue;
},
},
titleData: {
set(newValue) {
this.$emit("update:title", newValue);
},
get() {
return this.title;
},
},
},
};
</script>
<style lang="scss" scoped></style>
4.绑定的data是一个对象的时候
App.vue
<template>
<!-- 绑定两个v-model -->
<!-- 组件是可以传参数的,在冒号后面
这时候子组件里面就多了一个props属性title,
也多了一个emits事件"update:title""
-->
<hy-input v-model="data"></hy-input>
<h2>{{ data.name }}</h2>
<h2>{{ data.title }}</h2>
<button @click="btnclick">button</button>
</template>
<script>
import HyInput from "./HyInput.vue";
import { ref } from "vue";
export default {
components: {
HyInput,
},
setup() {
const data = ref({
name: "why",
title: "vue3",
});
const btnclick = () => {
data.value.name = "chang name";
data.value.title = "new title";
//对ref对象里面的某个属性修改的话,也是响应式的。
};
return {
data,
btnclick,
};
},
};
</script>
<style></style>
HyInput.vue
<template>
<div>
<input v-model="data['name']" /> <input v-model="data['title']" />
{{ modelValue }}
{{ data }}
</div>
</template>
<script>
import { ref, watch } from "vue";
export default {
props: {
modelValue: {
type: Object,
required: true,
},
},
emits: ["update:modelValue"],
/* setup(props, { emit }) {
const data = computed({
get: () => props.modelValue,
set: (newValue) => {
emit("update:modelValue", newValue);
},
});
按照只有一个数据的时候的那种写法,看起来也是可以的,
但是实际上,data.title或者data.name的值改变的时候,
set函数式不会触发的,所有只能get,不能set。
但是这个时候父组件的值也有相对应的改变,
那是因为这个时候相当于
子组件直接oninput事件改变了data.name的值,
因为你拿data.title,实际上就是把input的值给props.modelValue.value,所以oninput的时候,
也会把input的value给props.modelValue.value,
实际上还是单向绑定。
*/
//第一点,表单里面的input的v-model绑定的
//一定不是props过来的data,只有一个数据的话,
//式给这个数据一个相对应的计算属性,v-model绑定这个计算属性。从而操作。
//第二点,我们props传过来的这个对象里面有很多数据,
//每个都给一个computed属性,很麻烦,
//我们直接复制一个对象给子组件,子组件监听变化
setup(props, { emit }) {
//reactive在进行双向绑定的时候,多少有些问题,推荐使用ref
const data = ref({ ...props.modelValue });
//这样写的话,就data变成了响应式,
//一旦modelValue发生变化的话,data也就会发生变化。
//但是data发生变化,modelValue不会发生变化。
//把props.modelValue的属性全部拷贝一份给这个data变量。
//现在这个data和以前的props.modelValue就没有任何关系了
//这个时候data里面的两个属性就和两个input双向绑定住了
//改变input里面的东西,这个data属性有改变,
//但是父元素里面的data,也就是props.modelValue是没有改变的
watch(
data,
(newValue) => {
console.log(newValue);
emit("update:modelValue", newValue);
},
{ deep: true, immediate: true }
);
return { data };
},
};
</script>
<style lang="scss" scoped></style>
网友评论