自定义事件

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

<div id="app3">
<my-component v-on:myclick="onClick"></my-component>
</div>
<script>
Vue.component('my-component', {
template: `<div>
<button type="button" @click="childClick">点击我触发自定义事件</button>
</div>`,
methods: {
childClick () {
this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
}
}
})
new Vue({
el: '#app3',
methods: {
onClick () {
console.log(arguments)
}
}
})
</script

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

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

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

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

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

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

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

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

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

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

绑定原生事件

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

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

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

<div id="app4">
<input type="text" v-bind:value="text" v-on:input="changeValue($event.target.value)">
{{text}}
</div>
<script>
new Vue({
el: '#app4',
data: {
text: '444'
},
methods: {
changeValue (value) {
this.text = value
}
}
})
</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 选项可以用来避免这样的冲突:

<div id="app5">
<base-checkbox v-model="lovingVue"></base-checkbox>
<div>{{lovingVue}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `<input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)"> `
})
var vm = new Vue({
el: "#app5",
data: {
lovingVue: false
}
})
</script>

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

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

动态组件

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

<div id="app6">
<select v-model="currentComponent">
<option value="home">home</option>
<option value="posts">post</option>
<option value="archive">about</option>
</select>
<component :is="currentComponent"></component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
new Vue({
el: '#app6',
data: {
currentComponent: 'home'
},
components: {
home: {
template: `<header>这是home组件</header>`
},
posts: {
template: `<header>这是posts组件</header>`
},
archive: {
template: `<header>这是archive组件</header>`
}
}
})
</script>
保留切换出去的组件,避免重新渲染

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

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

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

<component></component>

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

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

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

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

列子

   <div id="app"> //父组件模板:
<h1>我是父组件的标题</h1>
<my-component>
<p>这是一些初始内容</p>
</my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
new Vue({
el: "#app",
data: {},
components: {
'my-component': {
template: `
<div>//子组件的模板
<h2>我是子组件的标题</h2>
<slot>
只有在没有要分发的内容时才会显示。
</slot>
</div> `
}
}
})
</script>

渲染 结果:

<div>
<h1>我是父组件的标题</h1>
<div>
<h2>我是子组件的标题</h2>
<p>这是一些初始内容</p>
</div>
</div>
具名slot

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

注意

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

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

<div id="app">
<app-layout>
<h1 slot="header">这里可能是一个页面标题</h1>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
<p slot="footer">这里有一些联系信息</p>
</app-layout>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
new Vue({
el: "#app",
data: {},
components: {
'my-component': {
template: `
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div> `
}
}
})
</script>

渲染结果:

<div class="container">
<header>
<h1>这里可能是一个页面标题</h1>
</header>
<main>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
</main>
<footer>
<p>这里有一些联系信息</p>
</footer>
</div>
作用域插槽

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

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

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

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

<div id="app7">
<my-component4>
<template scope="props">
</template>
</my-component4>
</div>

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

props = {
text: '',
message: ''
}

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

<div id="app7">
<my-component4>
<template slot-scope="props">
<span>{{props.text}}</span>
<span>{{props.message}}</span>
</template>
</my-component4>
</div>

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

<div id="app7">
<my-component4>
<template slot-scope="{text, message}">
<span>{{text}}</span>
<span>{{message}}</span>
</template>
</my-component4>
</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. 学习 vue 需要了解的内容

    总结 vue 的目录 1. vue 基础 指令 事件 动态的属性 组件 动画 2. vue 组件通信 1. 父传子 props 2. 子传父 ref 3. 插槽 4. 组件的生命周期 3. vue 的 ...

  2. ftp列出具体目录的所有目录,和目录按照文件类型列出

    package com.haiyisoft.cAssistantWeb.util; import java.io.IOException; import java.io.PrintWriter; im ...

  3. [eclipse]如何修改Eclipse编辑器的字体

    步骤如下, 菜单->"Window"->“Preference”->“General”->“Appearance”->“Colors & Fo ...

  4. nvl(sum(字段),0) 的时候,能展示数据0,但是group by 下某个伪列的时候,查不到数据(转载)

    今天碰到一个比较有疑惑的问题,就是在统计和的时候,我们往往有时候查不到数据,都会再加个 nvl(sum(字段),0) 来显示这个字段,但是如果我们再加个group by ,就算有加入这个 nvl(nu ...

  5. 一句话说明Facbook React证书的矛盾点

    这项专利授权说,如果您要使用我们根据这项授权发布的软件,假如您因为专利侵权而提起诉讼,您将失去我们的专利许可.

  6. PLSQL报错: ORA-12514:TNS:监听程序当前无法识别连接描述符中请求的服务

    一开始吓尿了,以为自己动着什么东西了把数据库玩坏了,谁知道打开服务发现服务没启动........... 我们要确保数据库服务是启动状态

  7. mintUI 移动UI框架入门

    入门地址: http://mint-ui.github.io/#!/zh-cn 下载依赖cd到项目目录下, 下载我们用的UI框架: 分为全局引入和按需引入 全局引入: npm install mint ...

  8. Web jsp开发学习——数据库的另一种连接方式(配置静态数据库连接池)

    1.导包   2.找到sever里的sever.xml,配置静态数据库连接池 <Context docBase="bookstore" path="/booksto ...

  9. nginx主配置文件实例

    1.修改配置文件 重要:修改配置文件使用虚拟机,否则怎么配置都不生效,添加如下用户 [root@host-10-1-1-161 html]# ll /etc/nginx/nginx.conf -rw- ...

  10. DVD Cloner 2019MAC如何使用?

    DVD Cloner 2019 for mac是一款应用在Mac上的DVD刻录软件,它可以将DVD克隆到任何空白光盘,包括具有多种复制模式的DVD + R / RW,DVD-R / RW,DVD + ...