当前位置:首页 > 技术文章 > 正文内容

Vue3开发极简入门(15.1):emits补完-结合v-model

zonemu2个月前 (07-08)技术文章32

之前代码是通过按钮触发emit,如果希望输入框里的内容在输入之后也能同步到父组件,就可以结合v-model的update事件来操作,具体如下。

Son2.vue:

<template>
    <div class='son2'>
        <h1>子组件2</h1>
        上报司机:{{ driverName }}<br />
        <input type="text" :value="driverName" @input="handleInput($event)" placeholder="输入司机姓名" />
    </div>
</template>

<script lang='ts' setup name='Son2'>
import { ref } from 'vue';
const driverName = ref('')
const props = defineProps(['driverName']);
const emit = defineEmits(['update:driverName']);

const handleInput = (event: Event) => {
    const target = event.target as HTMLInputElement;
    driverName.value = target.value
    emit('update:driverName', target.value);
};
</script>

<style scoped>
.son2 {
    background-color: rgb(85, 193, 236);
    padding: 10px;
    margin-top: 10px;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
    width: 90%;
    margin: auto;
}
</style>

父组件修改:

<template>
    <div class="father">
        <h1>父组件</h1>
        司机:{{ driverName }}<br />
        装货地:北京,卸货地:海口,发车时间:{{ departTime }}
        <Son @set-depart-time="setDepartTime" />
        <!--如果子组件传多个属性,可以直接在后面加,例如 v-model:dirverId="driverId"-->
        <Son2 v-model:driverName="driverName" />


    </div>
</template>
<script lang='ts' setup name='Father'>
import { ref } from 'vue';
import Son from './Son.vue';
import Son2 from './Son2.vue';

const departTime = ref('待定')
const driverName = ref('无')

function setDepartTime(val: string) {
    departTime.value = val
}
</script>
<style scoped>
.father {
    background-color: darkseagreen;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
    height: 100%;
}
</style>

整个流程,就是子组件的输入框绑定了输入回调函数handleInput,然后触发update事件,而父组件的v-model会监听此事件,并自动更新绑定的数据。子组件需要通过defineProps来接收父组件传递的值。

如果大家搜网上的资料,代码中的driverName大多是写成modelValue。modelValue适用1个属性,如果传递多个属性给父组件,例如司机姓名、司机身份证号等,就可以用文中的写法。

高版本的(3.4+),有比较简单的写法,就是defineModel语法糖,其本质就是自动生成defineProps、defineEmits。

Son2.vue修改如下:

<template>
    <div class='son2'>
        <h1>子组件2</h1>
        <label>
            司机ID:
            <input type="number" v-model="driverId">
        </label>
        <label>
            司机姓名:
            <input v-model="driverName">
        </label>
    </div>
</template>

<script lang='ts' setup name='Son2'>
import { ref } from 'vue';

const driverId = defineModel('driverId', {
    type: Number, default: 0, required: true, set(value: number) { // 数字输入校验
        return isNaN(value) ? 0 : Number(value);
    }
})
const driverName = defineModel('driverName')
</script>

<style scoped>
.son2 {
    background-color: rgb(85, 193, 236);
    padding: 10px;
    margin-top: 10px;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
    width: 90%;
    margin: auto;
}
</style>

父组件修改:

<template>
    <div class="father">
        <h1>父组件</h1>
        司机:{{ driverName }}<br />
        司机ID:{{ driverId }}<br />
        装货地:北京,卸货地:海口,发车时间:{{ departTime }}
        <Son @set-depart-time="setDepartTime" />
        <Son2 v-model:driverName="driverName" v-model:driver-id="driverId" />
    </div>
</template>
<script lang='ts' setup name='Father'>
import { ref } from 'vue';
import Son from './Son.vue';
import Son2 from './Son2.vue';

const departTime = ref('待定')
const driverName = ref('无')
const driverId = ref(0)

function setDepartTime(val: string) {
    departTime.value = val
}
</script>
<style scoped>
.father {
    background-color: darkseagreen;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
    height: 100%;
}
</style>

请注意看看父子组件driverId和driverName写法的不同,我是故意这么写的:

  • 子组件定义driverId的写法,比较全,包含了类型定义、默认值、是否必填、校验&转换。
  • 父组件关于driverId的写法,“driverId”是父组件自己的,而driver-id是子组件defineModel('driverId')的那个dirverId。这一点我忘了在props一节中说明:可以使用驼峰形式(driverName用的就是),但是Vue官网上说为了和HTML attribute对齐,通常会将其写为kebab-case(短横线)形式。实际工作中,看公司自己的规范写吧。
  • TypeScript对类型要求严格,可以写作const driverName = defineModel<string>('driverName')

相关文章

Gitlab 的使用和代码审查流程介绍

1、先简洁介绍下项目常用的信息-面板统计页面2、用户信息面板3、服务器信息4、项目信息5、重点介绍代码提交审核机制和授权合并机制开发人员推送代码的时候不能直接推送到master,否则就会报错。此时开发...

程序员效率提升!使用自动化工具gitx,每周节约半小时

你是否经历过这样的折磨?一个 JIRA 需求要同时修复 dev、qa、staging 三个分支每个版本涉及 A、B、C 三个项目手动执行以下操作:从 dev 切临时分支cherry-pick 提交推送...

VIM配置整理(vim配置教程)

一、基本配色set number set showcmd set incsearch set expandtab set showcmd set history=400 set autoread se...

在html5页面中如何使用vue3(html页面引入vue组件)

今天是2021.7.14,是个好日子.好久没发布文章了.今天发布下如何在在html页面中使用vue3.义县游学电子科技一直以技术文章为主.以下是h5的页面源码:<html><scri...

HTML5与APP的抉择(h5与app的区别)

同为当下炙手可热的技术,围绕APP和HTML5难免少不了各种争辩。而在“互联网+”时代,许多面临转型的传统企业,也在选择转型工具时,陷入了HTML5或APP的纠结抉择之中……到底该选择HTML5还是A...

12种JavaScript中最常用的数组操作整理汇总

数组是最常见的数据结构之一,我们需要绝对自信地使用它。在这里,我将列出 JavaScript 中最重要的几个数组常用操作片段,包括数组长度、替换元素、去重以及许多其他内容。1、数组长度大多数人都知道可...