Skip to content

父组件

vue
<template>
    <Rating v-model="value"></Rating>
</template>
<script setup lang="ts">
    import { ref } from 'vue'
    import Rating from '@/components/Rating/index.vue' // 导入组件

    const value = ref(0)
</script>

子组件

vue
<template>
    <view class="rating">
		<view v-for="(item, index) in starNum" :key="index"
			class="l-icons icon-xingxing" :class="[index+1 <= modelValue ? 'icon-select' : 'icon-noselect']"
			:style="{color: index+1 <= modelValue ? activeColor : unActiveColor, fontSize: fontSize}" @click="ratingClick(index)">
		</view>
	</view>
</template>
<script setup lang="ts">
    import { ref } from 'vue'
    type Props = {
		modelValue: number, // 父组件写v-model时,收到的参数
	}
	const props = withDefaults(defineProps<Props>(), {
		modelValue: 0,
	})

    const emit = defineEmits<{
		(event: 'update:modelValue', value:number): void
	}>()

	const ratingClick = (index) => {
        // 更新父组件的值
		emit('update:modelValue', index+1)
	}

    // 定义当前组件暴露出去的属性,父组件通过ref方式能够调用
    defineExpose({

    })
</script>

组件双向绑定

v-model可以在组件上实现双向绑定。 当前v-model使用在原生元素上时:

html
<input v-model="text"/>

编译模板会对v-model进行更冗长的等价展开。所以上面的代码等价于下面的代码:

html
<input value="text" @input="text => $event.target.value" />

当v-model使用在组件上时,v-model会被展开:

html
<Rating :modelValue="text" @update:modelValue="newValue => text = newValue"></Rating>

要让列子实际工作起来,我们需要在子组件Rating内部做两件事

  • 将内部的值绑定到modelValue上
  • 当内部值触发改变时,触发一个携带新的值update:modelValue自定义事件
vue
<template>
    <view class="rating" @click="ratingClick(index)">
        {{ modelValue }}
	</view>
</template>
<script setup lang="ts">
    import { ref } from 'vue'
    type Props = {
		modelValue: number, // 父组件写v-model时,收到的参数
	}
	const props = withDefaults(defineProps<Props>(), {
		modelValue: 0,
	})

    const emit = defineEmits<{
		(event: 'update:modelValue', value:number): void
	}>()

	const ratingClick = () => {
        // 更新父组件的值
		emit('update:modelValue', props.modelValue + 1)
	}
</script>

modelValue为默认v-model参数。如下,如果这样,modelValue就替换成title

v-model:title="text"

Released under the MIT License.