Vue3手册译稿 - 深入组件 - 自定义事件

vue

本章节需要掌握组件基础

emit我译成发射,觉得发射这个词比较形象的形容将子组件事件发射出来的一个动作。

事件名

像组件和props,事件名也会进行自动转换,如果你在子组件里发射一个驼峰命名的事件,你就可以在父组件中添加一个短横线分隔的监听:

this.$emit('myEvent')

<my-component @my-event="doSomething"></my-component>

因为有props情形存在,模板内DOM议使用短横线分隔命名方式。如果你使用字符串模板,则不存在这个限制。

自定义事件定义

Vue School自定义事件视频教程

自定义事件发射(请子组件传递到父组件)可以通过emits选项:

app.component('custom-form', {

emits: ['inFocus', 'submit']

})

当在emits中定义了一个原生事件(如click)时,组件事件将会代替原生事件监听。

提示

推荐定义所有已发射的事件,以便记录组件是如何工作的

验证已射事件

prop类型验证一样,一个已发射事件如果通过对象语法而不是数组语法,也可以被验证。

添加一个验证,事件会分配一个函数来接收参数,并传递给$emit调用,返回一个布尔值来确认事件是否有效。

app.component('custom-form', {

emits: {

// 无验证

click: null,

// 验证提交事件

submit: ({ email, password }) => {

if (email && password) {

return true

} else {

console.warn('不合法的 submit 事件加载!')

return false

}

}

},

methods: {

submitForm() {

this.$emit('submit', { email, password })

}

}

})

v-model参数

默认组件的v-model使用modelValue作为prop和update:modelValue作为事件。我们可以传递一个参数给v-model修改这些名称:

<my-component v-model:title="bookTitle"></my-component>

app.component('my-component', {

props: {

title: String

},

emits: ['update:title'],

template: `

<input

type="text"

:value="title"

@input="$emit('update:title', $event.target.value)">

`

})

在这个案例中,子组件会同步接收titleprop,发射update:title事件:

app.component('my-component', {

props: {

title: String

},

emits: ['update:title'],

template: `

<input

type="text"

:value="title"

@input="$emit('update:title', $event.target.value)">

`

})

<my-component v-model:title="bookTitle"></my-component>

v-model绑定

正如前面所学习v-model参数,我们可以为同一个组件实例添加多个v-model参数。

每个v-model可以与不同的prop相同步,组件不需要额外的选项:

<user-name

v-model:first-name="firstName"

v-model:last-name="lastName"

></user-name>

app.component('user-name', {

props: {

firstName: String,

lastName: String

},

emits: ['update:firstName', 'update:lastName'],

template: `

<input

type="text"

:value="firstName"

@input="$emit('update:firstName', $event.target.value)">

<input

type="text"

:value="lastName"

@input="$emit('update:lastName', $event.target.value)">

`

})

我们来写一个完整点的例子,实现一个区号-座机输入组件,结果如下图:

代码如下:

<!DOCTYPE html>

<html lang="en-US">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width,initial-scale=1">

<title>component v-model</title>

<script src="https://unpkg.com/vue@next"></script>

</head>

<body>

<div >

<tel-input v-model:tel-number="telNumber" v-model:area-number="areaNumber"></tel-input>

<p>

{{areaNumber}}-{{telNumber}}

</p>

</div>

</body>

<script type="text/javascript">

const data_and_methods = {

data() {

return {

telNumber: '',

areaNumber: ''

}

},

methods: {

}

}

const app = Vue.createApp(data_and_methods)

app.component('tel-input',{

props: {

areaNumber:String,

telNumber:String

},

emits: ['update:areaNumber','update:telNumber'],

template: `

<input placeholder="区号" type="number" class="area-number" :value="areaNumber" @input="$emit('update:areaNumber',$event.target.value)" />

-

<input placeholder="座机号码" type="number" class="tel-number" :value="telNumber" @input="$emit('update:telNumber',$event.target.value)" />

`

})

app.mount("#app")

</script>

<style type="text/css">

.area-number {width:60px;}

</style>

</html>

处理v-model修饰符

在前面我们学习输入绑定时,v-model有一些内置的修饰符如.trim,.number,.lazy等。有些情形,你也想增加一些自定义的修饰符。

让我们来创建一个capitalize修饰符,使用v-model绑定将输入首字母转换为大写。

组件v-model修饰符通过modelModifersprop提供给组件。下面的例子,我们创建了一个含有默认为空对象 的modelModifiersprop组件。

注意在组件created生命周期勾子触发器中,modelModifiersprop包含capitalize且值是true - 当它被设置在v-model绑定v-model.capitalize="myText"

<my-component v-model.capitalize="myText"></my-component>

app.component('my-component', {

props: {

modelValue: String,

modelModifiers: {

default: () => ({})

}

},

emits: ['update:modelValue'],

template: `

<input type="text"

:value="modelValue"

@input="$emit('update:modelValue', $event.target.value)">

`,

created() {

console.log(this.modelModifiers) // { capitalize: true }

}

})

现在我们设置好了prop,我们检测modelModifiers对象的键,然后通过方法处理要发射出去的值。下面我们来把输入框的首字母转换为大写:

<!DOCTYPE html>

<html lang="en-US">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width,initial-scale=1">

<title>component v-model modifiers</title>

<script src="https://unpkg.com/vue@next"></script>

</head>

<body>

<div >

<my-component v-model.capitalize="myText"></my-component>

<p>{{ myText }}</p>

</div>

</body>

<script type="text/javascript">

const data_and_methods = {

data() {

return {

myText: ''

}

}

}

const app = Vue.createApp(data_and_methods)

app.component('my-component',{

props: {

modelValue: String,

modelModifiers: {

default: () => ({})

}

},

emits: ['update:modelValue'],

template: `

<input type="text"

:value="modelValue"

@input="emitValue" />

`,

methods: {

emitValue(e){

let value = e.target.value

if(this.modelModifiers.capitalize){

value = value.charAt(0).toUpperCase() + value.slice(1)

}

this.$emit('update:modelValue',value)

}

},

created() {

console.log(this.modelModifiers)

}

})

app.mount("#app")

</script>

</html>

v-model绑定参数,生成的prop名将会是arg+"modelModifiers"

<my-component v-model:description.capitalize="myText"></my-component>

app.component('my-component', {

props: ['description', 'descriptionModifiers'],

emits: ['update:description'],

template: `

<input type="text"

:value="description"

@input="$emit('update:description', $event.target.value)">

`,

created() {

console.log(this.descriptionModifiers) // { capitalize: true }

}

})

以上是 Vue3手册译稿 - 深入组件 - 自定义事件 的全部内容, 来源链接: utcz.com/z/377506.html

回到顶部