Vue 的数据流传递是单向的,也就说数据只能由父组件通过props
传递给子组件,子组件无法修改父组件传过来的状态,这样做为了避免因为子组件修改父组件的状态而导致数据流混乱以至难以理解。所以千万不要在子组件中直接修改 props。
子组件如果想要将数据传递给父组件,就需要使用 Vue 提供的事件机制,利用emit()
方法将数据传递过去。但是请注意,这并没有改变 Vue 单向数据流的本质,数据还是由父组件流向子组件。
在 Vue 中,使用v-model
指令可以在<input>
、<checkbox>
、<select>
等 HTML 原生表单元素上实现双向数据绑定,它负责监听用户的输入事件并更新数据,但是v-model
只是一个语法糖,本质还是使用事件机制,就是上面说的emit()
方法来实现双向数据。有如下一个输入框
<input type="text" v-model="searchText" />
其实等价于下面这种形式:
<input type="text" :value="searchText" @input="searchText = $event.target.value" />
Vue2 自定义组件 v-model
v-model
指令不仅可以在原生的 HTML 元素上使用,也可以在自定义组件上使用。
我们封装一个子组件BaseForm.vue
,
<!-- 子组件 BaseForm.vue -->
<script>
export default {
name: 'BaseForm',
// 自定义prop和事件
model: {
event: 'form:update',
prop: 'formData',
},
props: {
// v-model绑定的值
formData: {
type: Object,
default: () => ({}),
},
},
data() {
return {
// 使用currentValue避免子组件直接修改props
// 使用父组件传递过来的props初始化这个值
currentValue: {
...this.formData,
},
};
},
};
</script>
<template>
<form class="base-form">
<div class="form-control">
<input type="text" placeholder="username or email" v-model="currentValue.username" />
</div>
<div class="form-control">
<input type="password" placeholder="password" v-model="currentValue.password" />
</div>
<div class="form-control">
<input type="checkbox" v-model="currentValue.checked" />
</div>
<div class="form-control">
<button @click="$emit('form:update', currentValue)">Submit</button>
</div>
</form>
</template>
默认情况下,组件上的v-model
会利用名为value
的 prop 和名为input
的事件,如果想要传递自定义的的 prop 和事件,可以通过model
选项进行指定。这里我们把 prop 指定为formData
,事件指定为form:update
,但是需要注意的是,在父组件中需要为v-model
指定参数为formData
,例如:
<script>
export default {
data() {
return {
loginForm: {},
};
},
methods: {
handleFormUpdate(formData) {
console.log(formData);
},
},
};
</script>
<BaseForm v-model:formData="loginForm" @form:update="handleFormUpdate"></BaseForm>
如果项目中使用了 ESLint 的话,使用这种语法,eslint 会提示
'v-model' directives require no argument
,意思是不建议在v-model
上指定参数,如果真的需要的话,可以关闭这条规则:'vue/no-v-model-argument': 'off'
。一般情况下使用默认的value
就够了。
最后,在通过自定义的事件form:update
将数据传给父组件:
<button @click="$emit('form:update', currentValue)">Submit</button>
Vue3 自定义组件 v-model
Vue3 中的v-model
有些许变化:
- 内部原生
<input>
元素的value
属性绑定到名为modelValue
的 prop - 原生
input
事件触发时,会触发update:modelValue
自定义事件
<script setup>
defineProps(['modelValue']);
defineEmits(['update:modelValue']);
</script>
<template>
<div class="base-input">
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</div>
</template>
如果我们想要像 Vue2 中指定自定义的 prop 和事件,不需要用model
选项,直接在defineProps()
和defineEmits()
方法中指定即可:
<script setup>
import { reactive } from 'vue';
const props = defineProps({
formData: {},
});
defineEmits(['form:update']);
const currentValue = reactive({ ...props.formData });
</script>
在父组件中使用:
<BaseForm v-model:form-data="loginForm" @form:update="handleFormUpdate" />
标签:自定义,formData,props,prop,Vue3,组件,model
From: https://www.cnblogs.com/gnefengv2/p/17608277.html