[笔记][Vue.js]打开Vue.js世界的大门(12)-让组件与父元素沟通的$emit和v-model的绑定篇

嗨!让我抓住礼拜天的尾巴,继续研究Vue.js吧XD,之后就要分心处理React了,那废话不多说,分隔线下进入正文!


对父级做事件处理

首先提一下关于组件的事件处理,昨天有在文章中提到官方的一个例子:
HTML

<div id="demoCounter">    <button-counter></button-counter></div>

JavaScript

Vue.component('button-counter',{    data:()=>{        return {            count:0,        }    },    template:`<div>                  <button @click="count++">Click me</button>                  <span>目前点了{{count}}下</span>              </div>`})let demoCounter = new Vue({    el:'#demoCounter',})

上方在设定组件时我们把事件写再button@click里面,让他被点击时可以把count加1,但是这仅仅于组件控制组件的资料而已,试着想想当把count的值放到demoCounterdata中时,组件内的事件该怎么控制count加1呢?如果遇到这种情况可以使用Vue.js中的内建方法$emit传入事件名字,让他对父层组件demoCounter触发用v-on绑定的事件名称:
HTML

<div id="demoCounter">    <!--再使用组件时设定组件内部监听的$emit事件名称来触发父组件的事件-->    <button-counter @add-count="addCount"></button-counter>    <!--把count从内部组件移到外面-->    <span>目前点了{{count}}下</span></div>

JavaScript

Vue.component('button-counter',{    template:`<div>                  <!--在组件内部使用v-on绑定$emit方法,传入事件名称-->                  <button @click="$emit('add-count')">Click me</button>              </div>`,})let counterData = {    count:0,}let counterMethods = {    //被触发的事件在这边    addCount:()=>{        counterData.count+=1;    }}    let demoCounter = new Vue({    el:'#demoCounter',    data:counterData,    methods:counterMethods,})

http://img2.58codes.com/2024/20106935MqfENYO63R.jpg
如上方使用$emit建立让外层组件监听的事件,就可以触发并更改父组件的方法及资料。

然后这里在使用事件的时候也有需要注意的地方,那就是$emit传入的方法名称会全部变成小写,而且和之前在设定组件名称时不同,就算在这里使用驼峰命名法,他在外面v-on的时候也不会帮你转换成短横线命名法,也就是说驼峰式命名法在这里完全无用武之地,以下是例子:
HTML

<!--使用驼峰式命名法让父组件监听事件名称--><button @click="$emit('addCount')">Click me</button><!--如果像上方$emit设定,以下两种写法都不会被触发--><button-counter @add-count="addCount"></button-counter><button-counter @add-count="add-count"></button-counter><!--他会被转成小写的版本,所以只有以下写法会被触发--><button-counter @add-count="addcount"></button-counter>------------------分隔线------------------<!--如果一开始是短横线命名法--><button @click="$emit('add-count')">Click me</button><!--不需另外转换写法也会被触发--><button-counter @add-count="add-count"></button-counter>

所以说,官方在这里注明了,不如就使用$emit时只以短横线命名法处理,当然如果平时就是用短横线命名法就不需要在意这个了。

另一点是,有时候父组件上监听的事件会需要一个或以上的参数传入处理,所以$emit他第一个参数如上面所说是呼叫父组件的事件名称,这边也要感谢fysh711426大大留言补充关于参数的部分,如果是由$emit指定事件,并额外传入参数给父组件的话,$emit会把第二个以后的全部参数都放到arguments这个物件中,也就是说父组件如果要获取子组件藉由$emit传的参数,必须使用arguments[0]代表第一个参数、arguments[1]代表第二个参数..等等,我们看下方例子:
HTML

<div id="demoCounter">    <!--在父组件上用arguments来接收子组件传的参数-->    <button-counter @add-count="addCount(arguments)"></button-counter>    <span>目前点了{{count}}下</span></div>

JavaScript

Vue.component('button-counter',{    template:`<div>                  <!--在组件内部使用v-on绑定$emit方法,传入事件名称外多传了两个参数-->                  <button @click="$emit('add-count','传入一个参数','传入第二个参数')">Click me</button>              </div>`,})let counterData = {    count:0,}let counterMethods = {    addCount:(arrArg)=>{        //在事件内分别印出arrArg物件,和第一个值还有第二个值        console.log(arrArg)        console.log(arrArg[0])        console.log(arrArg[1])        counterData.count+=1;    }}    let demoCounter = new Vue({    el:'#demoCounter',    data:counterData,    methods:counterMethods,})

结果会如下:
http://img2.58codes.com/2024/20106935hOGLRiJSk0.jpg

接着来提好久不见的v-model吧!

在组件上使用v-model

之前的文章中有说过,v-model其实是个语法糖,也就是让各位大大用起来觉得甜甜的(咦?),先複习一下吧!v-model到底帮我们做了哪些事:

<input v-model="message" />

会等于:

<input :value="message" @input="message = $event.target.value" />

上面的观念之前的文章中有提过(还不熟的可以看这里),所以应该不会有太大的问题,但在组件上直接使用v-model是不会有任何作用的,所以当我们知道v-model的原理以后,也可以用相同的方式放到让v-model在组件上实现。

但是一口气说完,第一个想法可能是「天啊!这是什么鬼?」,所以这个部分让我们大部分解一下过程:

在组件上设定Props属性,并用指定value来绑定inputvalue值,有没有初始值都没关係,但是为了做到v-modelv-bind:value="value"必须这么做。
JavaScript
Vue.component('inputName',{    //用props属性来为组件内的DOM绑定资料    props:['value'],    template:`<div>                  <!--这边的观念是:value="message"的部分-->                  <input :value='value' >              </div>`,})
接着要处理v-model帮我们做的第二件事情@input="message = $event.target.value",但是我们v-model绑定的资料在父组件的data中,所以用上面学到的$emit来控制和触发父组件的事件,而上面也有说过$emit的第一个参数为触发父组件的事件名称,那我们的事件名称是什么?先回头看一下HTML的部分:
HTML
<div id="demoInput">    <!--在组件里用v-model绑定父组件data中的nameVal-->    <input-name v-model="nameVal"></input-name>    <span>我的名字是:{{nameVal}}</span></div>

单就<input-name v-model="nameVal"></input-name>这一行,大家应该可以知道他做了哪些事情吧?他会等于:
HTML

<input-name :value="nameVal" @input="nameVal=$event.target.value"></input-name>

欸嘿嘿!聪明的你发现父组件的事件了吗?没错!就是input,所以$emit要绑定的事件名称就是input,但是光是呼叫到input还是不够的,因为父组件的input会用$event.target.value的值去指定给nameVal,所以在事件后方要再多加一个参数,让父组件的input接收,所以设定第二个参数为input的值:$event.target.value
JavaScript

Vue.component('inputName',{    props:['value'],    template:`<div>                  <!--加上了@input="message = $event.target.value"的观念,并用$emit来触发父组件的input事件-->                  <input :value='value' @input="$emit('input', $event.target.value)">              </div>`,})//这里是父组件,绑定的资料在data中let demoInput = new Vue({    el:'#demoInput',    data:{        nameVal:'',    },})

最后的程式码,把所有注解拿掉会如下方这样子,也完成了在组件中实做v-model,虽然看起来没有几行,但是却用到了之前提到的不少观念,所以如果有不懂得可以看一下前面的几篇文章,或是自己练习看看,都会加深一点印象!
HTML

<div id="demoInput">    <input-name v-model="nameVal"></input-name>    <span>我的名字是:{{nameVal}}</span></div>

JavaScript

Vue.component('inputName',{    props:['value'],    template:`<div>                  <input :value='value' @input="$emit('input', $event.target.value)">              </div>`,})let demoInput = new Vue({    el:'#demoInput',    data:{        nameVal:'',    },})

http://img2.58codes.com/2024/2010693546jGfJDVwp.jpg
得到的结果就和我们一般使用的<input v-model="nameVal" />一样对吧!但没想到加入组件后会变的那么难懂,不过还是老话一句,熟能生巧,虽然感觉我发文很频繁,不过每次在写範例的时候还是会一直偷看之前自己发的文XD。


最后感谢大大们的观看!如果文章中有任何解释不清楚或理解错误的地方,还请各位大大留言告诉我,另外有任何想法也都欢迎留言和我讨论,不管是什么我都会认真看过的!谢谢大家http://img2.58codes.com/2024/emoticon41.gif


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章