一、组合式API里的写法
1、defineModel
defineModel()返回的值是一个ref,它可以像其他ref一样被访问以及修改,不过它能起到在父组件和当前变量之间的双向绑定的作用。
- 它的.value和父组件的v-model的值一起更新
- 当它的子组件变更了,会触发父组件绑定的值一起更新
因为defineModel声明了一个prop,你可以通过给它传递选项,来声明底层prop的选项
javascript">const model = defineModel('modelValue', {
requiew: true, // 必填
default: 0, // 默认值
type: Number // 类型
})
注意:该写法需Vue3.2.0及以上版本才支持
1个数据的双向绑定
javascript">// 父组件<template><p>{{ data }}</p>
<button @click="data = 'xxx2'">修改子组件数据</button><Subcomponent v-model="data" /></template><script lang="ts" setup>import { ref } from 'vue'
import Subcomponent from './components/Subcomponent.vue'const data = ref('xxx1')</script>
javascript">// 子组件
<template><h1>{{ modelValue }}</h1>
<button @click="updateData('xxx2')">修改父组件的数据</button></template><script lang="ts" setup>import { defineModel } from 'vue'const modelValue = defineModel()const updateData = (e: string) => {modelValue.value = e
}</script>
多个数据的双向绑定
javascript">// 父组件<template><p>{{ data1 }}</p>
<p>{{ data2 }}</p>
<button @click="data1 = 'xxx2'">修改子组件的数据1</button>
<button @click="data2 = 'xxx2'">修改子组件的数据2</button><Subcomponent v-model:data1="data1" v-model:data2="data2" /></template><script lang="ts" setup>import { ref } from 'vue'
import Subcomponent from './components/Subcomponent.vue'const data1 = ref('data1')
const data2 = ref('data2')</script>
javascript">// 子组件
<template><h1>{{ data1 }}</h1>
<h1>{{ data2 }}</h1>
<button @click="updateData1('xxx1')">修改父组件的数据1</button>
<button @click="updateData2('xxx2')">修改父组件的数据2</button></template><script lang="ts" setup>import { defineModel } from 'vue'const data1 = defineModel('data1')
const data2 = defineModel('data2')const updateData1 = (e: string) => {data1.value = e
}const updateData2 = (e: string) => {data2.value = e
}</script>
2、v-model
1个数据的双向绑定
javascript">// 父组件<template><p>{{ data }}</p>
<button @click="data = 'xxx2'">修改子组件数据</button><Subcomponent v-model="data" /></template><script lang="ts" setup>import { ref } from 'vue'
import Subcomponent from './components/Subcomponent.vue'const data = ref('xxx1')</script>
javascript">// 子组件
<template><h1>{{ modelValue }}</h1>
<button @click="updateData('xxx2')">修改父组件的数据</button></template><script lang="ts" setup>const props = defineProps<{ modelValue: string }>()
const emit = defineEmits<(e: "update:modelValue", value: string) => void>()const updateData = (e: string) => {emit('update:modelValue', e)
}</script>
多个数据的双向绑定
javascript">// 父组件<template><p>{{ data1 }}</p>
<p>{{ data2 }}</p>
<button @click="data1 = 'xxx2'">修改子组件的数据1</button>
<button @click="data2 = 'xxx2'">修改子组件的数据2</button><Subcomponent v-model:data1="data1" v-model:data2="data2" /></template><script lang="ts" setup>import { ref } from 'vue'
import Subcomponent from './components/Subcomponent.vue'const data1 = ref('data1')
const data2 = ref('data2')</script>
javascript">// 子组件
<template><h1>{{ modelValue }}</h1>
<button @click="updateData1('xxx2')">修改父组件的数据1</button>
<button @click="updateData2('xxx2')">修改父组件的数据2</button></template><script lang="ts" setup>const props = defineProps<{
data1: string,
data2: string
}>()const emit = defineEmits<{
(e: "update:data1", value: string): void,
(e: "update:data2", value: string): void,
}>()const updateData1 = (e: string) => {emit('update:data1', e)
}const updateData2 = (e: string) => {emit('update:data2', e)
}
</script>
3、常规写法
javascript">// 子组件<template><p>{{ p_data }}</p><button @click="updateData('xxx')">子组件按钮</button>
</template><script lang="ts" setup>const props = defineProps<{ p_data: string }>()const emit = defineEmits<(e: "update", value: string) => void> ()function updateData(e: string) {emit('update', '修改父组件data')
}</script>
javascript">// 父组件<template><p>{{ data }}</p>
<button @click="data = 'xxx2'">修改子组件数据</button><Subcomponent :p_data="data" @update="updateData"/></template><script lang="ts" setup>import { ref } from 'vue'
import Subcomponent from './components/Subcomponent.vue'const data = ref('xxx1')function updateData(e: string) {data.value = e
}</script>
二、选项式API里的写法
javascript">// 子组件
<template>
<input :value="modelValue" @input="handleInput" />
</template><script>export default {props: {modelValue: String // 定义v-model绑定的属性名},emits: ['update:modelValue'] // 声明可以发出的自定义事件
}</script>
javascript">// 父组件
<template>
<CustomInpput v-model="inputValue" />
</template><script>
import CustomInput from './CustomInput.vue'export default {components: {CustomInput},data() {return {inputValue: ''}}
}
</script>
三、案例 —— 自定义勾选按钮
javascript"><template><div class="component-container"><i class="check-btn" v-if="!isChecked" @click="handleCheck(true)"></i><i class="check-btn active" v-if="isChecked" @click="handleCheck(false)"></i></div>
</template><script lang="ts" setup>import { ref, defineModel } from 'vue'const emits = defineEmits(['change'])const isChecked = defineModel('isChecked', { default: false })function handleCheck(e: boolean) {isChecked.value = eemits('change', isChecked.value)
}</script><style lang="scss" scope>
.component-container {.check-btn {display: block;border: 1px solid #d4d4d9;width: 15px;height: 15px;cursor: pointer;&.active {background: #0055FF;}}
}
</style>
<CheckBtn @change="(...args) => managementFieldCheckAll(...args, it.value)"/>