Vue2的v-model默认解析成:value与@input
Vue3的v-model默认解析成:modelValue与@update:modelValue
所以要是想通过封装组件支持v-model的使用,用v-model语法糖无疑是最好的选择
子组件定义使用modelValue进行接收父组件传递过来的值,定义事件update:modelValue通知父组件改变一些事情
举例使用:封装子组件用法:cp-radio-btn
//子组件 cp-radio-btn
<script setup lang="ts">
// 通过v-model双向绑定实现计数器
const props = defineProps<{
modelValue: number
}>()
const emit = defineEmits<{
(e: 'update:modelValue', count: number): void
}>()
const btnClick = () => {
emit('update:modelValue', props.modelValue + 10)
}
</script>
<template>
<div class="cp-radio-btn">
计数器:{{ modelValue }} <br />
<button @click="btnClick">修改count</button>
//<button @click="$emit('update:modelValue', modelValue + 2)">修改count</button>
</div>
</template>
<style lang="scss" scoped></style>
父组件patient -使用子组件cp-radio-btn
使用 modelValue 像子组件传递数据,定义子组件通知的事件 @update:modelValue做事情
//父组件 patient
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const count = ref(0)
const updateCount = (num: number) => {
count.value = num
}
</script>
<cp-radio-btn :modelValue="count" @update:modelValue="updateCount"></cp-radio-btn>
//<cp-radio-btn :modelValue="count" @update:modelValue="count = $event"></cp-radio-btn>
如此就完成了数据的双向绑定;
在这,:modelValue="count" @update:modelValue="updateCount"就可以简写为v-model="count"
可以实现同上代码同样的效果
<cp-radio-btn v-model="count"></cp-radio-btn>
上面文章开始说了Vue3的v-model默认是解析成了:modelValue与@update:modelValue,下面说一下,如果你想修改这个默认的传值与事件的话,如何修改?
举个例子:这里换传值事件名字时(这里用OtherName举例)
使用v-model后面需要加上:OtherName
<cp-radio-btn v-model:OtherName="count"></cp-radio-btn>
子组件的传值以及事件都需要改为自定义的名称
<script setup lang="ts">
// 通过v-model双向绑定实现计数器
const props = defineProps<{
OtherName: number
}>()
const emit = defineEmits<{
(e: 'update:OtherName', OtherName: number): void
}>()
const btnClick = () => {
emit('update:OtherName', props.OtherName + 10)
}
</script>
<template>
<div class="cp-radio-btn">
计数器:{{ OtherName }} <br />
<button @click="btnClick">修改OtherName</button>
</div>
</template>
<style lang="scss" scoped></style>
封装一个自定义单选按钮组件 cp-radio-btn,满足下方需求
贴出代码 :
<script setup lang="ts">
defineProps<{
options: { label: string; value: number | string }[]
modelValue?: number | string
}>()
defineEmits<{
(e: 'update:modelValue', value: number | string): void
}>()
</script>
<template>
<div class="cp-radio-btn">
<a
class="item"
href="javascript:;"
v-for="item in options"
:key="item.value"
:class="{ active: modelValue == item.value }"
@click="$emit('update:modelValue', item.value)"
>{{ item.label }}</a
>
</div>
</template>
<style lang="scss" scoped>
.cp-radio-btn {
display: flex;
flex-wrap: wrap;
.item {
height: 32px;
min-width: 60px;
line-height: 30px;
padding: 0 14px;
text-align: center;
border: 1px solid var(--cp-bg);
background-color: var(--cp-bg);
margin-right: 10px;
box-sizing: border-box;
color: var(--cp-text2);
margin-bottom: 10px;
border-radius: 4px;
transition: all 0.3s;
&.active {
border-color: var(--cp-primary);
background-color: var(--cp-plain);
}
}
}
</style>
使用组件:
<cp-radio-btn :options="timeOptions" v-model="form.illnessTime" />
使用vant 的van-action-sheet动作面板组件封装一个支付组件 cp-pay-sheet
cp-pay-sheet文章来源:https://www.toymoban.com/news/detail-437882.html
<script setup lang="ts">
import { showToast, showLoadingToast } from 'vant'
import { ref } from 'vue'
import { getConsultOrderPayUrl } from '@/services/consult'
const props = defineProps<{
orderId: string
actualPayment: number
onClose?: () => void
show: boolean
}>()
const emit = defineEmits<{
(e: 'update:show', val: boolean): void
}>()
const paymentMethod = ref<0 | 1>()
// 跳转支付
const pay = async () => {
if (paymentMethod.value === undefined) return showToast('请选择支付方式')
showLoadingToast({ message: '跳转支付', duration: 0 })
const res = await getConsultOrderPayUrl({
orderId: props.orderId,
paymentMethod: paymentMethod.value,
payCallback: 'http://localhost:5173/room'
})
window.location.href = res.data.payUrl
}
</script>
<template>
<!-- 支付方式弹窗 -->
<van-action-sheet
:show="show"
@update:show="emit('update:show', $event)"
title="选择支付方式"
:close-on-popstate="false"
:closeable="false"
:before-close="onClose"
>
<div class="pay-type">
<p class="amount">¥20.00</p>
<van-cell-group>
<van-cell title="微信支付" @click="paymentMethod = 0">
<template #icon><cp-icon name="consult-wechat" /></template>
<template #extra><van-checkbox :checked="paymentMethod == 0" /></template>
</van-cell>
<van-cell title="支付宝支付" @click="paymentMethod = 1">
<template #icon><cp-icon name="consult-alipay" /></template>
<template #extra><van-checkbox :checked="paymentMethod == 1" /></template>
</van-cell>
</van-cell-group>
<div class="btn">
<van-button type="primary" round block @click="pay">立即支付</van-button>
</div>
</div>
</van-action-sheet>
</template>
<style lang="scss" scoped>
.pay-type {
.amount {
padding: 20px;
text-align: center;
font-size: 16px;
font-weight: bold;
}
.btn {
padding: 15px;
}
.van-cell {
align-items: center;
.icon-page {
margin-right: 10px;
font-size: 18px;
margin-top: 6px;
}
.van-checkbox :deep(.van-checkbox__icon) {
font-size: 16px;
}
}
}
</style>
使用组件文章来源地址https://www.toymoban.com/news/detail-437882.html
<cp-pay-sheet
v-model:show="show"
:order-id="orderId"
:actual-payment="payInfo.actualPayment"
:on-close="onClose"
></cp-pay-sheet>
到了这里,关于vue3 的v-model语法糖的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!