在html中使用元素,会有一些属性,如class,id,还可以绑定事件,自定义组件也是可以的。当在一个组件中,使用了其他自定义组件时,就会利用子组件的属性事件来和父组件进行数据交流。

  父子组件之间的通信就是 props down,events up,父组件通过 属性props向下传递数据给子组件,子组件通过 事件events 给父组件发送消息

  比如,子组件需要某个数据,就在内部定义一个prop属性,然后父组件就像给html元素指定特性值一样,把自己的data属性传递给子组件的这个属性。而当子组件内部发生了什么事情的时候,就通过自定义事件来把这个事情涉及到的数据暴露出来,供父组件处理。

<my-component v-bind:foo="baz" v-on:event-a="doThis(arg1,...arg2)"></my-component>

  如上代码:

    foo<my-component>组件内部定义的一个prop属性,baz是父组件的一个data属性,

    event-a是子组件定义的一个事件,doThis是父组件的一个方法

  过程就是这样:

    父组件把baz数据通过prop传递给子组件的foo

    子组件内部得到foo的值,就可以进行相应的操作;

    当子组件内部发生了一些变化,希望父组件能知道时,就利用代码触发event-a事件,把一些数据发送出去;

    父组件把这个事件处理器绑定为doThis方法,子组件发送的数据,就作为doThis方法的参数被传进来;

    然后父组件就可以根据这些数据,进行相应的操作。

1、属性Props

  Vue组件通过props属性来声明一个自己的属性,然后父组件就可以往里面传递数据。

Vue.component('mycomponent',{
template: '<div>这是一个自定义组件,父组件传给我的内容是:{{myMessage}}</div>',
props: ['myMessage'],
data () {
return {
message: 'hello world'
}
}
})

  然后调用该组件

<div id="app">
<mycomponent :my-message="hello"></mycomponent>
</div>

  注意,由于HTML特性是不区分大小写的,所以传递属性值时,myMessage应该转换成 kebab-case (短横线隔开式)my-message="hello"

2、v-bind绑定属性值

  这里说一下v-bind绑定属性值的一个特性:一般情况下,使用v-bind给元素特性(attribute)传递值时,Vue会将""中的内容当做一个表达式。比如:

<div attr="message">hello</div>
//上面这样,div元素的attr特性值就是message。 //而这样
<div v-bind:attr="message">hello</div>
//这里的message应该是Vue实例的data的一个属性,这样div元素的attr特性值就是message这个属性的值。

  之所以说是一般情况,是因为classstyle特性并不是这样。用v-bind:classclass传入正常的类名,效果是一样的,因为对于这两个特性,Vue采用了合并而不是替换的原则。

3、子组件希望对传入的prop进行操作

  一般来说,是不建议在子组件中对父组件中传递来的属性进行操作的。如果真的有这种需求,可以这样:

  父组件传递了一个基本类型值,那么可以在子组件中创建一个新的属性,并以传递进来的值进行初始化,之后就可以操作这个新的属性

props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}

  父组件传递了一个引用类型值,为了避免更改父组件中相应的数据,最好是对引用类型进行复制。复杂的情况,肯定应该是深复制

4、给子组件传递正确类型的值

  同样是上面的原因,静态的给子组件的特性传递值,它都会把他当做一个字符串。

<!-- 传递了一个字符串 "" -->
<comp some-prop=""></comp>

  子组件中,特性的值是字符串 "1" 而不是 number 1。如果想传递正确的数值,应该使用v-bind传递,这样就能把传递的值当做一个表达式来处理,而不是字符串。

<!-- 传递实际的 number  -->
<comp v-bind:some-prop=""></comp>

5、Prop验证

  我们可以给组件的props属性添加验证,当传入的数据不符合要求时,Vue会发出警告。

Vue.component('example', {
props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
propA: Number,
// 多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数字,有默认值
propD: {
type: Number,
default:
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value >
}
}
}
})

  type 可以是下面原生构造器:String、Number、Boolean、Function、Object、Array、Symbol

  type 也可以是一个自定义构造器函数,使用 instanceof 检测。

// 自定义Person构造器
function Person(name, age) {
this.name = name
this.age = age
}
Vue.component('my-component', {
template: `<div>名字: {{ person-prop.name }}, 年龄: {{ person-prop.age }} </div>`,
props: {
person-prop: {
type: Person // 指定类型
}
}
})
new Vue({
el: '#app2',
data: {
person: // 传入Number类型会报错
}
})

6、非Prop类型的属性

  也可以像在html标签中添加data-开头的自定义属性一样,给自定义组件添加任意的属性,而不仅限于data-*形式,这样做的话,Vue会把这个属性放在自定义组件的根元素上。一个自定义组件的模板只能有一个根元素

  覆盖非Prop属性:如果父组件向子组件的非prop属性传递了值,那么这个值会覆盖子组件模板中的特性

<div id="app3">
<my-component2 att="helloParent"></my-component2>
</div>
<script>
Vue.component('my-component2', {
template: `<div att="helloChild">子组件原有的特性被覆盖了</div>`
})
new Vue({
el: '#app3'
})
</script>

  上面渲染的结果是,divatt属性是helloParent

  注意:前面已经提到过,覆盖原则对于classstyle不适用,而是采用了合并(merge)的原则

<div id="app3">
<my-component2 att="helloParent" class="class2" style="color: red;"></my-component2>
</div>
<script>
Vue.component('my-component2', {
template: `<div att="helloChild" class="class1" style="background: yellow;">子组件原有的特性被覆盖了</div>`
})
new Vue({
el: '#app3'
})
</script>

  上面的渲染结果是,div的类名是class1 class2,行内样式是color:red; background:yellow;

7、自定义事件

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

<div id="app3">
<my-component2 v-on:myclick="onClick"></my-component2>
</div>
<script>
Vue.component('my-component2', {
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>

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

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

this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
  • 第一个参数是自定义事件的名字

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

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

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

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

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

8、动态组件

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

<div id="app6">
<select v-model="currentComponent">
<option value="home">home</option>
<option value="post">post</option>
<option value="about">about</option>
</select>
<component :is="currentComponent"></component>
</div>
<script>
new Vue({
el: '#app6',
data: {
currentComponent: 'home'
},
components: {
home: {
template: `<header>这是home组件</header>`
},
post: {
template: `<header>这是post组件</header>`
},
about: {
template: `<header>这是about组件</header>`
}
}
})
</script>

  也可以直接绑定到组件对象上:

var Home = {
template: `<header>这是home组件</header>`
}
new Vue({
el: '#app6',
data: {
currentComponent: Home
}
})

9、保留切换出去的组件,避免重新渲染

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

<keep-alive>
<component :is="currentComponent">
<!-- 非活动组件将被缓存! -->
</component>
</keep-alive>

深入理解Vue父子组件通讯的属性和事件的更多相关文章

  1. Vue父子组件通讯

    我们知道,父组件不能修改子组件的数据[这种说法是不严谨的],严谨的说法是:子组件内部不能修改从父组件传递过来的值.原因是vue遵循的是数据单向流原则,父组件传递数据给子组件只能单向绑定,通过Props ...

  2. 【Vue】Vue中的父子组件通讯以及使用sync同步父子组件数据

    前言: 之前写过一篇文章<在不同场景下Vue组件间的数据交流>,但现在来看,其中关于“父子组件通信”的介绍仍有诸多缺漏或者不当之处, 正好这几天学习了关于用sync修饰符做父子组件数据双向 ...

  3. 【转】vue父子组件之间的通信

    vue父子组件之间的通信 在vue组件通信中其中最常见通信方式就是父子组件之中的通性,而父子组件的设定方式在不同情况下又各有不同.最常见的就是父组件为控制组件子组件为视图组件.父组件传递数据给子组件使 ...

  4. Angular6 基础(数据绑定、生命周期、父子组件通讯、响应式编程)

    Angular相比于vue来说,更像一个完整的框架,本身就集成了很多模块,如路由,HTTP,服务等,而vue是需要另外引入比如(vuex,axios等).Angular引入了依赖注入.单元测试.类等后 ...

  5. vue父子组件

    vue父子组件 新建 模板 小书匠  为什么要厘清哪个是父组件,哪个是子组件? 一开始浏览器接收和要显示的数据非常少,此时无需划分区域进行布局.随着页面数据量的增加,如果单纯一个窗口来加载和显示数据, ...

  6. vue的组件通讯

    Vue的组件通讯又称组件传值 一.父子组件传值: 父组件: <子组件名   :动态变量名 (随便起)='你想要传递的数据' ></子组件名> 子组件: 利用 prop去接收父组 ...

  7. Angular组件——父子组件通讯

    Angular组件间通讯 组件树,1号是根组件AppComponent. 组件之间松耦合,组件之间知道的越少越好. 组件4里面点击按钮,触发组件5的初始化逻辑. 传统做法:在按钮4的点击事件里调用组件 ...

  8. vue父子组件之间传值

    vue父子组件进行传值 vue中的父子组件,什么是父组件什么是子组件呢?就跟html标签一样,谁包裹着谁谁就是父组件,被包裹的元素就是子组件. 父组件向子组件传值 下面用的script引入的方式,那种 ...

  9. vue父子组件的传值总结

    久违的博客园我又回来了.此篇文章写得是vue父子组件的传值,虽然网上已经有很多了.写此文章的目的就是记录下个人学习的一部分.接下来我们就进入主题吧! 在开发vue项目中,父子组件的传值是避免不掉的. ...

随机推荐

  1. python 文件操作 r w a

    python基础-文件操作   一.文件操作 对文件操作的流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件       打开文件时,需要指定文件路径和以何等方式打开文件, ...

  2. 转载:超级强大的vim配置(vimplus)--续集

    超级强大的vim配置(vimplus)--续集 原文地址:https://www.cnblogs.com/highway-9/p/5984285.html An automatic configura ...

  3. easyui 在子tabs中打开新tabs(关于easyUI在子页面增加显示tabs的一个问题)

    现在说的是在子页面点个按钮也能触发增加子页面的情况. 情景是,在父页面上有个div如: <div class="easyui-tabs" id="main" ...

  4. 【反演复习计划】【bzoj3994】约数个数和

    首先要用数学归纳证明一个结论,不过因为我实在是懒得打公式了... 先发代码吧. #include<bits/stdc++.h> #define N 50005 using namespac ...

  5. fullpage.js jq全屏滚动插件

    fullPage.js和fullPage都能实现全屏滚动,二者区别是:fullPage.js需依赖于JQuery库,而fullPage不需要依赖任何一个js库,可以单独使用. (代码演示效果并且可以下 ...

  6. 【C++】类的特殊成员变量+初始化列表

    参考资料: 1.黄邦勇帅 2.http://blog.163.com/sunshine_linting/blog/static/448933232011810101848652/ 3.http://w ...

  7. 《Java编程思想》笔记 第十章 内部类

    1.创建内部类对象 创建内部类对象(相当于new内部类对象) 外围类对象.new 内部类( ). 创建内部类对象一种方法是 外围类有一个方法返回内部类对象. 没有外围类对象就不能创建内部类对象,因为内 ...

  8. k8s的chart学习(下)

    1.开发自己的chart Kubernetes 给我们提供了大量官方 chart,不过要部署微服务应用,还是需要开发自己的 chart,下面就来实践这个主题. 1.1创建 chart 执行 helm ...

  9. 《锋利的JQuery》读书要点笔记2——DOM操作

    第三章 jQuery中的DOM操作 3.1 DOM(Document Object Model)操作的分类 1. DOM Core    例如:document.getElementsByTagNam ...

  10. SaaS多租户模式数据存储方案比较

    云计算多租户几乎用于所有软件即服务 (Software as a Service, SaaS) 应用程序,因为计算资源是可伸缩的,而且这些资源的分配由实际使用决定.话虽如此,用户可以通过 Intern ...