自定义事件

通过prop属性,父组件可以向子组件传递数据,而子组件的自定义事件就是用来将内部的数据报告给父组件的。

  1. <div id="app3">
  2. <my-component v-on:myclick="onClick"></my-component>
  3. </div>
  4. <script>
  5. Vue.component('my-component', {
  6. template: `<div>
  7. <button type="button" @click="childClick">点击我触发自定义事件</button>
  8. </div>`,
  9. methods: {
  10. childClick () {
  11. this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
  12. }
  13. }
  14. })
  15. new Vue({
  16. el: '#app3',
  17. methods: {
  18. onClick () {
  19. console.log(arguments)
  20. }
  21. }
  22. })
  23. </script

点击按钮 控制台打印出如下

如上所示,共分为以下步骤:

子组件在自己的方法中将自定义事件以及需要发出的数据通过以下代码发送出去

  1. this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')

第一个参数是自定义事件的名字

后面的参数是依次想要发送出去的数据

父组件利用v-on为事件绑定处理器

  1. <my-component2 v-on:myclick="onClick"></my-component2>

这样,在Vue实例的methods方法中就可以调用传进来的参数了

注意: 在使用v-on绑定事件处理方法时,不应该传进任何参数,而是直接写v-on:myclick="onClick",不然,子组件暴露出来的数据就无法获取到了

绑定原生事件

如果想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on

  1. <my-component v-on:click.native="doTheThing"></my-component>
探究v-model

v-model可以对表单控件实现数据的双向绑定,它的原理就是利用了绑定属性和事件来实现的。比如input控件。不使用v-model,可以这样实现数据的双向绑定:

  1. <div id="app4">
  2. <input type="text" v-bind:value="text" v-on:input="changeValue($event.target.value)">
  3. {{text}}
  4. </div>
  5. <script>
  6. new Vue({
  7. el: '#app4',
  8. data: {
  9. text: '444'
  10. },
  11. methods: {
  12. changeValue (value) {
  13. this.text = value
  14. }
  15. }
  16. })
  17. </script>

上面的代码同样实现了数据的双向绑定。其本质就是:

  • 把input的value特性绑定到Vue实例的属性text上,text改变,input中的内容也会改变
  • 然后把表单的input事件处理函数设置为Vue实例的一个方法,这个方法会根据输入参数改变Vue中text`的值
  • 相应的,在input中输入内容时,触发了input事件,把event.target.value传给这个方法,最后就实现了改变绑定的数据的效果。

而v-model就是上面这种方式的语法糖,也就是把上面的写法封装了一下,方便我们使用。

使用自定义事件创建自定义的表单输入组件

理解了v-model的内幕,也就可以把这个效果用在自定义表单组件上了。

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突:

  1. <div id="app5">
  2. <base-checkbox v-model="lovingVue"></base-checkbox>
  3. <div>{{lovingVue}}</div>
  4. </div>
  5. <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  6. <script>
  7. Vue.component('base-checkbox', {
  8. model: {
  9. prop: 'checked',
  10. event: 'change'
  11. },
  12. props: {
  13. checked: Boolean
  14. },
  15. template: `<input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)"> `
  16. })
  17. var vm = new Vue({
  18. el: "#app5",
  19. data: {
  20. lovingVue: false
  21. }
  22. })
  23. </script>

这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的属性将会被更新。

注意 你仍然需要在组件的 props 选项里声明 checked 这个 prop。

动态组件

通过使用保留的 元素,动态地绑定到它的 is 特性,可以让多个组件使用同一个挂载点,并动态切换

  1. <div id="app6">
  2. <select v-model="currentComponent">
  3. <option value="home">home</option>
  4. <option value="posts">post</option>
  5. <option value="archive">about</option>
  6. </select>
  7. <component :is="currentComponent"></component>
  8. </div>
  9. <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  10. <script>
  11. new Vue({
  12. el: '#app6',
  13. data: {
  14. currentComponent: 'home'
  15. },
  16. components: {
  17. home: {
  18. template: `<header>这是home组件</header>`
  19. },
  20. posts: {
  21. template: `<header>这是posts组件</header>`
  22. },
  23. archive: {
  24. template: `<header>这是archive组件</header>`
  25. }
  26. }
  27. })
  28. </script>
保留切换出去的组件,避免重新渲染

如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令参数:

  1. <!-- 失活的组件将会被缓存!-->
  2. <keep-alive>
  3. <component :is="currentComponent">
  4. </component>
  5. </keep-alive>
插槽
单个slot

上面用到的很多组件的使用方式是这样的:

  1. <component></component>

也就是说组件中是空的,没有放置任何文本或元素。但是原生的html元素都是可以进行嵌套的,div里面放table

什么的。自定义组件开闭标签之间也可以放置内容,不过需要在定义组件时使用slot。

slot相当于子组件设置了一个地方,如果在调用它的时候,往它的开闭标签之间放了东西,那么它就把这些东西放到slot中。

  • 当子组件中没有slot时,父组件放在子组件标签内的东西将被丢弃;
  • 子组件的slot标签内可以放置内容,当父组件没有放置内容在子组件标签内时,slot中的内容会渲染出来;
  • 当父组件在子组件标签内放置了内容时,slot中的内容被丢弃

列子

  1. <div id="app"> //父组件模板:
  2. <h1>我是父组件的标题</h1>
  3. <my-component>
  4. <p>这是一些初始内容</p>
  5. </my-component>
  6. </div>
  7. <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  8. <script>
  9. new Vue({
  10. el: "#app",
  11. data: {},
  12. components: {
  13. 'my-component': {
  14. template: `
  15. <div>//子组件的模板
  16. <h2>我是子组件的标题</h2>
  17. <slot>
  18. 只有在没有要分发的内容时才会显示。
  19. </slot>
  20. </div> `
  21. }
  22. }
  23. })
  24. </script>

渲染 结果:

  1. <div>
  2. <h1>我是父组件的标题</h1>
  3. <div>
  4. <h2>我是子组件的标题</h2>
  5. <p>这是一些初始内容</p>
  6. </div>
  7. </div>
具名slot

slot可以有很多个。那么子组件对于父组件放置的多余的内容如何放到各个slot中呢?方法就是子组件给每个slot起一个名字name,父组件放置多余的元素时,给每个元素的slot属性分配一个代表slot的名字。到时候,多余的内容就会根据自己的slot属性去找具有对应名字的slot元素。

注意

  • 子组件可以有一个匿名的slot,当分发的多余内容找不到对应的slot时,就会进入这里面
  • 如果子组件没有匿名的slot,当分发的多余内容找不到对应的slot时,就会被丢弃、

例如,假定我们有一个 app-layout 组件,它的模板为:

  1. <div id="app">
  2. <app-layout>
  3. <h1 slot="header">这里可能是一个页面标题</h1>
  4. <p>主要内容的一个段落。</p>
  5. <p>另一个主要段落。</p>
  6. <p slot="footer">这里有一些联系信息</p>
  7. </app-layout>
  8. </div>
  9. <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  10. <script>
  11. new Vue({
  12. el: "#app",
  13. data: {},
  14. components: {
  15. 'my-component': {
  16. template: `
  17. <div class="container">
  18. <header>
  19. <slot name="header"></slot>
  20. </header>
  21. <main>
  22. <slot></slot>
  23. </main>
  24. <footer>
  25. <slot name="footer"></slot>
  26. </footer>
  27. </div> `
  28. }
  29. }
  30. })
  31. </script>

渲染结果:

  1. <div class="container">
  2. <header>
  3. <h1>这里可能是一个页面标题</h1>
  4. </header>
  5. <main>
  6. <p>主要内容的一个段落。</p>
  7. <p>另一个主要段落。</p>
  8. </main>
  9. <footer>
  10. <p>这里有一些联系信息</p>
  11. </footer>
  12. </div>
作用域插槽

作用域插槽也是一个插槽slot,但是他可以把数据传递给到父组件的特定元素内,然后有父组件决定如何渲染这些数据。

1.首先,子组件的slot需要有一些特性(prop)

  1. Vue.component('my-component4', {
  2. template: `<div>
  3. <slot :text="hello" message="world"></slot>
  4. </div>`,
  5. data () {
  6. return {
  7. hello: [1,'2']
  8. }
  9. }
  10. })

2.父组件在调用子组件时,需要在里面添加一个template元素,并且这个template元素具有scope特性

  1. <div id="app7">
  2. <my-component4>
  3. <template scope="props">
  4. </template>
  5. </my-component4>
  6. </div>

scope特性的值,就代表了所有子组件传过来的数据组成的对象。相当于

  1. props = {
  2. text: '',
  3. message: ''
  4. }

3.最后,父组件就可以在template中渲染子组件传过来的数据了

  1. <div id="app7">
  2. <my-component4>
  3. <template slot-scope="props">
  4. <span>{{props.text}}</span>
  5. <span>{{props.message}}</span>
  6. </template>
  7. </my-component4>
  8. </div>

4.Vue支持将作用域插槽的属性解构。所以上述代码可以简写为:

  1. <div id="app7">
  2. <my-component4>
  3. <template slot-scope="{text, message}">
  4. <span>{{text}}</span>
  5. <span>{{message}}</span>
  6. </template>
  7. </my-component4>
  8. </div>

作用域插槽也是插槽,只不过是多加了些特性,然后父组件多进行了些处理。

vue组件之事件的更多相关文章

  1. vue组件添加事件@click.native

    1,给vue组件绑定事件时候,必须加上native ,否则会认为监听的是来自Item组件自定义的事件 2,等同于在子组件中:  子组件内部处理click事件然后向外发送click事件:$emit(&q ...

  2. vue组件原生事件以及路由

    1.组件 组件就是可以扩展HTML元素,封装可重用的HTML代码,可以将组件看作自定义的HTML元素 1.1组件注册 全局注册: 组件注册时,需要给他一个名字,如下: Vue.component('m ...

  3. vue组件---自定义事件

    首先简单回顾下组件事件及组件的复用 demo1:按钮事件 <div class="button_area"> <button-area></butto ...

  4. vue组件中—bus总线事件回调函数多次执行的问题

    在利用vue组件进行事件监听时发现,如果对N个vue组件实例的bus总线绑定同一事件的回调函数,触发任意组件的对应事件,回调函数至少会被执行N次,这是为什么呢? 为此,调研了普通对象的事件绑定和触发实 ...

  5. vue组件事件(极客时间Vue视频笔记)

    vue组件核心:事件 <body> <div class="app"> <todo-list></todo-list> {{mess ...

  6. React对比Vue(03 事件的对比,传递参数对比,事件对象,ref获取DOM节点,表单事件,键盘事件,约束非约束组件等)

    import React from 'react'; class Baby extends React.Component { constructor (props) { super(props) t ...

  7. Vue父组件与子组件传递事件/调用事件

    1.Vue父组件向子组件传递事件/调用事件 <div id="app"> <hello list="list" ref="child ...

  8. Vue基础-自定义事件的表单输入组件、自定义组件的 v-model

    Vue 测试版本:Vue.js v2.5.13 学习 Vue 的自定义事件的表单输入组件,觉得文档讲的不太细致,所以这里再细化一下: 如果不用 v-model,代码应该是这样: <myinput ...

  9. Vue组件绑定自定义事件

    Vue组件使用v-on绑定自定义事件: 可以分为3步理解: 1.在组件模板中按照正常事件机制绑定事件: template: '<button v-on:click="increment ...

随机推荐

  1. SQLServer 简单数据拆分

    --1. 旧的解决方法(sql server 2000)   create table tb(id int,value varchar(30)) insert into tb values(1,'aa ...

  2. Mac/Linux 编译安装redis

    一.下载安装 官网http://redis.io/ 下载最新的稳定版本,这里是3.2.0 sudu mv redis-.tar /usr/local/ sudo tar -zxf redis-.tar ...

  3. linux之gzip命令

    命令格式: gzip [选项] 压缩(解压缩)的文件名 参数: -d 将压缩文件解压. -l  对每个压缩文件,显示压缩文件的大小,未压缩文件的大小,压缩比,未压缩文件的名字 -v 对每一个压缩和解压 ...

  4. ajax post 请求

    $(".login_btn").click(function(){ if($(".user_").val()=="admin"&&a ...

  5. 阶段3 3.SpringMVC·_04.SpringMVC返回值类型及响应数据类型_1 搭建环境

    创建项目 使用骨架,创建webapp 为了创建项目更快速maven设置 archetypeCatalog internal 修改编译的版本 从昨天的课程内复制 相关的坐标.上面是版本锁定. 复制前端的 ...

  6. c# 匿名类型获取值

    代码片段: 读取 new{ ....} 方法1:转换为json对象 dynamic model = SaleOrderServices.GetGiftOrderById(WebHelper.GetQu ...

  7. CKeditor从Word粘贴格式问题

    在config.js中添加配置 config.pasteFromWordRemoveFontStyles = false;    config.pasteFromWordRemoveStyles = ...

  8. 日期格式存入字符类型之后,再转回datetime类型报错

    背景 最近我们迁移了一批服务器,因我们在azure portal 上新开的VM暂时默认只有英文系统,所以我们在开设好的数据库服务器的时候,都会重置数据库字符排序成中文,避免出现中文乱码问题,重置参考路 ...

  9. C语言基础:内置函数的调用

    #include<stdio.h>#include<math.h>#include<stdlib.h>#include<ctype.h>#include ...

  10. 我想学前端动画-CSS之transition

    Transition属性: 属性 描述 CSS transition 简写属性,用于在一个属性中设置四个过渡属性. 3 transition-property 规定应用过渡的 CSS 属性的名称.默认 ...