自定义组件

  1. 自定义组件的v-model

    首先我们先说一下在自定义组件中使用v-model的必要条件

    • 在自定义的组件中要有input(这里我们先不讨论单选复选框)
    • 在自定义组件的模板对象中要有props属性,且里面要含有一个value
    • 在自定义组件的input标签上要绑定value属性值为props中传入的值,且还需要发出一个input事件

    这样讲可能会有点难理解,还是上代码吧...

    <div id="app">
    <child-com v-model="message"></child-com>
    <span>{{ message }}</span>
    </div>
    <template id="childCom">
    <div>
    <input type="text" :value="value" @input='inputEvent'>
    </div>
    </template> <script>
    const childCom = {
    template: '#childCom',
    props: ['value'],
    methods: {
    inputEvent(event) {
    this.$emit('aaa', event.target.value)
    }
    },
    } const vm = new Vue({
    el: '#app',
    data: {
    message: '可以双向绑定的了'
    },
    components: {
    childCom
    }
    })
    </script>

    这是最终实现效果需要必备的,看完这些代码如果你是小白,你可能会有点不理解为什么要这样做,下面我告诉你原理。

    首先在我们使用的v-model 中,其内部实现的原理就是一个 value属性和一个input事件,其主要步骤就是,用v-bind绑定value,然后用input事件监听值的变化,当文本框中的值发生变化的时候,input事件就会触发,那么我们可以在input事件中获取到改变后的值然后赋值给value,这样是不是就完成了双向数据绑定了。上代码:

    <div id="app">
    <input type='text' :value='message' @input='inputEvent'>
    <span>{{ message }}</span>
    </div> <script>
    const vm = new Vue({
    el: '#app',
    data: {
    message: '可以双向绑定的了'
    },
    methods: {
    inputEvent(event) {
    this.message = event.target.value;
    }
    }
    })
    </script>

    就这样几个步骤,就达到了v-model的效果了,这就是他的原理,然后让我们深一步想,让自定义组件使用双向数据绑定。因为我们知道其内部就是value和input事件,

    所以有了如下代码:

    <div id="app">
    <child-com :value='message' @input='message=$event'></child-com> <!-- 此代码就这里和最开始代码不同 -->
    <span>{{ message }}</span>
    </div> <template id="childCom">
    <div>
    <input type="text" :value="value" @input='inputEvent'>
    </div>
    </template> <script>
    const childCom = {
    template: '#childCom',
    props: ['value'],
    methods: {
    inputEvent(event) {
    this.$emit('input', event.target.value)
    }
    },
    } const vm = new Vue({
    el: '#app',
    data: {
    message: '可以双向绑定的了'
    },
    components: {
    childCom
    }
    })
    </script>

    根据上面的原理,现在你应该知道了为什么要传一个value在子组件了吧,明白之后,您就可以把 <child-com :value='message' @input='message=$event'></child-com> 替换成 <child-com v-model="message"></child-com> 了。

  2. $listeners的使用

    由来:当我们在项目开发过程中会出现很多组件嵌套的关系,那么如果还要在最外层的组件向内部传递数据的话,有如下几种方式:

    • 从父向子传递,子再向孙传递,一直传递下去,那么最里面的组件想往最外层传东西则可以从最里面向外面逐层$emit发送出去,但是仔细想想,一个简单的传递信息,却涉及到了这之间所有的组件,而他们只是一个中间者,这让代码维护起来非常困难
    • 使用vuex来进行传递,这样确实方便了很多,但是这样做如果没有其他用处的话就有点大材小用了
    • 使用事件总线,这样使用也不容易维护

    $listeners$attrs 的出现,就完美的解决了第一种情况的发生

    <div id="app">
    <child-com :name='name' :age='age' @test-listeners='testListeners'></child-com>
    </div> <script>
    const vm = new Vue({
    el: '#app', // 父组件
    data: {
    name: 'lyl',
    age: 20,
    },
    methods: {
    testListeners(arg) {
    console.log(arg)
    }
    },
    components: {
    childCom: { // 子组件
    inheritAttrs: false,
    template: `
    <div>
    <span> {{name}} </span>
    <grand-com v-bind='$attrs' v-on='$listeners'></grand-com>
    </div>
    `,
    props: ['name'],
    components: {
    grandCom: { // 孙子组件
    inheritAttrs: false,
    template: `
    <div>
    <span @click='listenClick'>{{$attrs.age}}</span>
    </div>
    `,
    methods: {
    listenClick() {
    this.$emit('test-listeners','aaaaaaa');
    }
    },
    }
    }
    }
    }
    })
    </script>

    上面代码中,孙子组件要发出一个是将让父组件调用,这个时候我们可以在中间过渡的子组件模板使用的孙子组件上绑定这个属性,即:v-on='$listeners',这样一来父组件就能直接调用孙子组件发出的方法了,并且在中间层的子组件上并没有什么多余的部分

  3. .sync的使用方法

    我们都知道,在一个组件上,我们只能使用一个v-model,但是如果我们的组件中有多个input标签呢,并且每个input标签中的值都不同,且每个都想进行双向绑定,这个时候,v-model就不行了。于是乎就出现了.sync的出现。

    根据上面我说的那些需求,我们写一下代码:

    • 不使用.sync的代码
    <div id="app">
    <child-com
    :value='obj.value' @aaa='obj.value = $event'
    :name='obj.name' @bbb='obj.name = $event'
    :age='obj.age' @ccc='obj.age = $event'>
    </child-com> <p>{{ obj }}</p>
    <p>{{ obj.value }}</p>
    <p>{{ obj.name }}</p>
    <p>{{ obj.age }}</p>
    </div> <!-- childCom组件的模板 -->
    <template id="childCom">
    <div>
    <input type="text" :value="value" @input='inputValueEvent'>
    <br>
    <input type="text" :value="name" @input='inputNameEvent'>
    <br>
    <input type="text" :value="age" @input='inputAgeEvent'>
    </div>
    </template> <script>
    const childCom = {
    template: '#childCom',
    props: ['value','name','age'],
    methods: {
    inputValueEvent(event) {
    this.$emit('aaa', event.target.value)
    },
    inputNameEvent(event) {
    this.$emit('bbb', event.target.value)
    },
    inputAgeEvent(event) {
    this.$emit('ccc', event.target.value)
    }
    },
    } const vm = new Vue({
    el: '#app',
    data: {
    obj: { value: '双向绑定' , name: 'coderlyl' , age: 20}
    },
    components: {
    childCom
    }
    })
    </script>

    根据上面的代码,我们不难发现,我们在标签中书写了过多的重复的东西,可读性也不是很好,下面我们再使用 .sync 的方式

    • 使用.sync的代码
    <div id="app">
    <child-com v-bind:value.sync='obj.value'
    v-bind:name.sync="obj.name"
    v-bind:age.sync="obj.age"> <!--这里也发生了变化-->
    </child-com> <p>{{ obj }}</p>
    <p>{{ obj.value }}</p>
    <p>{{ obj.name }}</p>
    <p>{{ obj.age }}</p>
    </div>
    <template id="childCom">
    <div>
    <input type="text" :value="value" @input='inputValueEvent'>
    <br>
    <input type="text" :value="name" @input='inputNameEvent'>
    <br>
    <input type="text" :value="age" @input='inputAgeEvent'>
    </div>
    </template> <script>
    const childCom = {
    template: '#childCom',
    props: ['value','name','age'],
    methods: {
    inputValueEvent(event) {
    this.$emit('update:value', event.target.value) // 这里发生了变化
    },
    inputNameEvent(event) {
    this.$emit('update:name', event.target.value) // 这里发生了变化
    },
    inputAgeEvent(event) {
    this.$emit('update:age', event.target.value) // 这里发生了变化
    }
    },
    } const vm = new Vue({
    el: '#app',
    data: {
    message: '可以双向绑定的了',
    obj: { value: '双向绑定' , name: 'coderlyl' , age: 20}
    },
    components: {
    childCom
    }
    })
    </script>

    也许看完这里,你并没有觉得好到哪里去了,下面还有更简单的写法

    <child-com v-bind.sync="obj"></child-com>
    <!-- 其他代码一样 -->

    对,没错!这是终极简化版,但是这只针对于对象才能用

    注意带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。取而代之的是,你只能提供你想要绑定的属性名,类似 v-model

    v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”,是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑。

组件使用v-model、$listeners、.sync(区别于v-model的双向数据绑定)的更多相关文章

  1. vue中如何在自定义组件上使用v-model和.sync

    自定义事件 tips 推荐始终使用 kebab-case 的事件名.(v-on会将事件名自动转换为小写,避免匹配不到) changeData × change-data √ 自定义组件的v-model ...

  2. vue2组件之间双向数据绑定问题

    最近在使用element-ui的dialog组件二次封装成独立组件使用时,子组件需要将关闭dialog状态返回给父组件,简单的说就是要实现父子组件之间的数据双向绑定问题. 大致代码如下: 1,父组件 ...

  3. SIP模块版本错误问题:the sip module implements API v??? but XXX module requires API v???

    系统安装了python 2.7,继续安装PyQt4,于是依次下载sip.pyqt4源码进行安装.用以下代码测试: import PyQt4.QtGui 显示出错.错误信息:the sip module ...

  4. Angular自定义组件实现数据双向数据绑定

    学过Angular的同学都知道,输入框通过[(ngModel)]实现双向数据绑定,那么自定义组件能不能实现双向数据绑定呢?答案是肯定的. Angular中,我们常常需要通过方括号[]和圆括号()实现组 ...

  5. Angular4.x 创建组件|绑定数据|绑定属性|数据循环|条件判断|事件|表单处理|双向数据绑定

    Angular4.x 创建组件|绑定数据|绑定属性|数据循环|条件判断|事件|表单处理|双向数据绑定 创建 angular 组件 https://github.com/angular/angular- ...

  6. n维向量空间W中有子空间U,V,如果dim(U)=r dim(V)=n-r U交V !={0},那么U,V的任意2组基向量的组合必定线性相关

    如题取U交V中的向量p (p!=0), 那么p可以由 U中的某一组基线性组合成(系数不全是零),同时,-p也可以由V中的某一组基线性组合成(系数不全为零) 考察p+(-p)=0 可知道,U中的这组基跟 ...

  7. angular4自定义组件非input元素实现ngModel双向数据绑定

    在angular里我们一般都是给input元素添加[(ngModel)]="value"实现数据双向绑定,如果想实现自定义的组件上实现ngModel双向数据绑定应该怎么办呐... ...

  8. Angular:实现组件间双向数据绑定

    学过Angular的同学都知道,输入框通过[(ngModel)]实现双向数据绑定,那么父子组件间能不能实现双向数据绑定呢?答案是肯定的. Angular中,我们常常需要通过方括号[]和圆括号()实现组 ...

  9. vue3.x自定义组件双向数据绑定v-model

    vue2.x 语法 在 2.x 中,在组件上使用 v-model 相当于绑定 value prop 并触发 input 事件: <ChildComponent v-model="pag ...

随机推荐

  1. Codeforces_731_F

    http://codeforces.com/problemset/problem/731/F 其实是暴力枚举,但是有些小技巧,直接保存每个数的数量. 枚举每个起点时,然后依次加上起点大小的分段的数量的 ...

  2. HDU_1556_线段树

    http://acm.hdu.edu.cn/showproblem.php?pid=1556 直接用了技巧来做. #include<iostream> #include<cstdio ...

  3. avtivity与view

    view和activity的区别 activity相当于控制部分,view相当于显示部分.两者之间是多对多的关系,所有东西必须用view来显示.  viewGroup继承自view,实现了ViewMa ...

  4. 手写-- K-means++

    1. K-means++原理 K均值聚类属于启发式方法,不能保证收敛到全局最优,初始中心的选择会直接影响聚类结果.K-means是随机选择样本点作为聚类中心,容易造成算法局部收敛或者需要较多迭代次数, ...

  5. 网络安全初级实战笔记(一):owasp zap 暴力破解

    网络安全里装着好多人的侠客梦.但是不能触碰铁律,所以,只小小的自娱自乐. 自己练习,大都会用到DVWA,一个很好的安全测试平台,自己搭建(很简单,傻瓜式搭建),自己设置安全级别,自己验证各种漏洞攻击方 ...

  6. 前端项目引入Echarts中的dataTool的正确方式

    使用echarts画箱线图时调用echarts.dataTool.prepareBoxplotData() 报错:"echarts.dataTool.prepareBoxplotData i ...

  7. C语言基础五 数组的应用

    .根据用户输入的10人成绩并将其保存到数组中,求最高成绩,最低成绩和平均成绩 int scoure[10];//存储10个数据的数组 int i; int sum;//总成绩 int max,min, ...

  8. C语言三 语句练习

    输入一个整数day代表星期几,根据day的值输出对应的星期几,比如day==1,就输出“星期一”(用两种方式实现) int Day; printf("请输入一个1~7的数字"); ...

  9. javascript30--day01--Drum kit

    相关视频链接:https://www.bilibili.com/video/av8481988/?p=3 Drum kit 做题思路(1)监听键盘事件 addEventListener(‘事件名’,执 ...

  10. 源码浅析:InnoDB聚集索引如何定位到数据的物理位置,并从磁盘读取

    索引结构概述: MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址.这与Oracle的索引结构相似,比较好理解.那么,常用的Innodb聚集索引结构是怎样的呢? InnoDB的数据文 ...