组件的嵌套

在Vue的设计中,一切都可以看作组件。整个页面可以看作是一个根组件,内部的各块组件可以看作子组件。组件之间自然的会发生嵌套关系。

接下来,我们看一下组件嵌套的示例:

<div id="app"><my-table></my-table>
</div><template id="table-head"><thead><tr><th>id</th><th>name</th><th>age</th><th>gender</th></tr></thead>
</template><template id="table-body"><tbody><tr v-for="u in users" :key="u.id"><td>{{u.id}}</td><td>{{u.name}}</td><td>{{u.age}}</td><td>{{u.gender}}</td></tr></tbody>
</template><template id="my-table"><table border="1" align="center"><thead is="table-head"></thead><tbody is="table-body"></tbody></table>
</template>
<script>var tableHead = {template:"#table-head"}var tableBody = {template:"#table-body",data:function(){return {users: [{"id":1, "name": "小明", "age": 13, "gender": "男"},{"id":2, "name": "小红", "age": 13, "gender": "女"},{"id":3, "name": "小绿", "age": 4, "gender": "男"}]}}}//使用局部注册,需要将子组件注册到父组件中var myTable ={template:"#my-table",components:{"table-head":tableHead,"table-body":tableBody}}const vm = new Vue({el:"#app",components:{"my-table":myTable}});
</script>

说明:事实上,虽然 new Vue() 没有显式的使用组件的语法,但它本质上也是一个父组件。

组件通信

通常一个较为复杂的页面,一定会出现组件的嵌套。各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。

1. 父传子:props

通常父组件的模板中包含子组件,父组件要正向地向子组件传递数据或参数,子组件接收到后根据参数的不同来渲染不同的内容或执行操作。这个正向传递数据的过程就是通过props来实现的。

比如在之前的表格案例中,table-body子组件展示的数据是定义在子组件自个身上的,这么做虽有效果,但降低了该组件的复用价值,更好的做法:子组件中不定义数据,而是由使用它的父组件传递。此时,需要使用 props完成父组件向子组件的数据传递。

语法:
//1.定义子组件中添加props属性
const 组件 = {
template:“html片段”,
props:[“自定义参数名”,…]
}
//2 使用组件时,为组件添加 自定义参数名 同名的属性
<组件 :自定义参数名=”值"></组件>

例子:

<div id="app"><my-table :us="users"></my-table>
</div><template id="my-table"><table border="1" align="center"><thead><tr><th>id</th><th>name</th><th>age</th><th>gender</th></tr></thead><tbody><tr v-for="u in us" :key="u.id"><td>{{u.id}}</td><td>{{u.name}}</td><td>{{u.age}}</td><td>{{u.gender}}</td></tr></tbody></table></template><script>var myTable = {template:"#my-table",props:["us"]}const vm = new Vue({el:"#app",data:{users: [{"id":1, "name": "小明", "age": 13, "gender": "男"},{"id":2, "name": "小红", "age": 13, "gender": "女"},{"id":3, "name": "小绿", "age": 4, "gender": "男"}]},components:{"myTable":myTable}});
</script>

2. 子传父:$emit

父组件的模板中包含子组件,那么经常会出现子组件的状态发生变化时,要通知到父组件。所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。如下所示:

代码如下:

<div id="app"><h2>{{num}}</h2><!--
父组件向子组件传递数据 count=num
子组件中修改count值,不能修改父组件的num
--><counter :count="num"></counter>
</div><script>Vue.component("counter",{template:`
<div>
<button @click="increment">点我自增</button>
<span>{{count}}</span>
<button @click="decrement">点我自减</button></div>`,props:["count"],methods:{increment(){this.count++;},decrement(){this.count--;}}})const vm = new Vue({el:"#app",data:{num:0}})
</script>

所以,当需要子传父的时候,Vue采用事件放射的方式完成。

  • 在子组件中执行 $emit(“父组件的自定义事件”)通知父组件,并发送数据
  • 父组件中定义自定义事件处理函数,并接收数据
<div id="app"><h2>{{num}}</h2><!-- 2 绑定自定义事件处理函数,监听子组件的事件触发 change-count当子组件触发事件后,执行handleChange事件处理函数,$emit发送的数据将成为handleChange的实参--><counter :count="num" @change-count="handleChange"></counter>
</div><script>Vue.component("counter",{template:`<div><button @click="increment">点我自增</button><span>{{count}}</span><button @click="decrement">点我自减</button></div>`,props:["count"],methods:{increment(){this.count++;//1 子组件中通过$emit触发父组件中的自定义事件,并发送数据this.$emit("change-count",this.count);},decrement(){this.count--;//1 子组件中通过$emit触发父组件中的自定义事件,并发送数据this.$emit("change-count",this.count);}}})const vm = new Vue({el:"#app",data:{num:0},methods:{handleChange(value){this.num = value;}}})
</script>

实战案例

代码如下:

<div id="app"><div><my-table :us="users" @show-user="handleShowUser"></my-table><hr><update-form :u="user" @update-user="handleUpdateUser"></update-form></div>
</div>
<template id="my-table"><table border="1"><thead><tr><th>id</th><th>name</th><th>age</th><th>operation</th></tr></thead><tbody><tr v-for="(u,index) in us" :key="u.id"><td>{{u.id}}</td><td>{{u.name}}</td><td>{{u.age}}</td><td><button @click="emitShowUser(u)">更新</button></td></tr></tbody></table>
</template>
<template id="update-form"><form action="" @submit.prevent="emitUpdateUser"><input type="hidden" v-model="u.id" >用户名: <input type="text" v-model="u.name"> <br>年龄: <input type="number" v-model="u.age"> <br><input type="submit" value="更新"></form>
</template><script>const updateForm = {template:"#update-form",props:["u"],methods:{emitUpdateUser(){this.$emit("update-user",this.u);}}};const myTable = {template:"#my-table",props:["us"],methods:{emitShowUser(u){this.$emit("show-user",u);}}};const vm = new Vue({el:"#app",data:{users:[{id:1,name:"xiao1hei",age:18},{id:2,name:"xiao2hei",age:20},{id:3,name:"xiao3hei",age:22}],user:{}},components:{myTable,updateForm},methods:{handleShowUser(u){this.user = JSON.parse(JSON.stringify(u));},handleUpdateUser(u){this.users.forEach((item,i,users)=>{if(item.id == u.id){//由于Vue2.x无法直接检测到数组中元素的变化,可以使用vue提供的$set方法this.$set(this.users,i,JSON.parse(JSON.stringify(u))g);}})}}})
</script>

Vue第二部分(2):组件的嵌套与通信相关推荐

  1. vue 嵌套表格组件_使用form-create动态生成vue自定义组件和嵌套表单组件

    使用form-create动态生成vue自定义组件和嵌套表单组件 maker.create 通过建立一个虚拟 DOM的方式生成自定义组件 生成 Maker let rule = [ formCreat ...

  2. Vue第二天学习总结—— Vue全家桶之组件化开发(组件化开发思想、组件注册、Vue调试工具用法、组件间数据交互传递、组件插槽、基于组件的案例——购物车)

    (一) 组件化开发思想 1. 现实中的组件化思想体现 组件化即是对某些可以进行复用的功能进行封装的标准化工作 标准:要想组件能够成功组合在一起,每个组件必须要有标准 分治:将不同的功能封装到不同的组件 ...

  3. Vue第二章,在项目中使用element-ui组件

    使用vue的童鞋相信都知道vue中有很多ui组件,这里推荐使用element-ui组件(个人测试还算强大,起码开发商野心不小),因为此组件可以集成到angular.react.vue任意一个框架中. ...

  4. 实例化vue对象 绑定子组件_Vue-双向数据绑定

    实例 Vue.js应用的创建很简单,通过构造函数 Vue 就可以创建一个 Vue 的根实例,并启动 Vue: var app = new Vue({//选项 }); 变量 app 就代表了这个 Vue ...

  5. vue中在当前组件中定义的全局变量怎么在methods中使用_Vue原理解析(十):搞懂事件API原理及在组件库中的妙用...

    在vue内部初始化时会为每个组件实例挂载一个this._events私有的空对象属性: vm._events = Object.create(null) // 没有__proto__属性 这个里面存放 ...

  6. 【Vue基础七】--- 组件和模块概念

    文章目录 一. 组件 1-1 传统方式和组件的对比 1-2 模块和组件概念 1-2-1 模块+模块化 1-2-2 组件化 1-3 组件 1-3-1 非单文件组件 1-3-1-1 组件的使用 1-3-1 ...

  7. Vue2基础、组件化编程、脚手架、Vuex、Vue路由、UI组件库

    尚硅谷张天禹老师讲课 学习视频 1.Vue简介 Vue2中文官网 1.1 Vue 介绍 一套用于构建用户界面的渐进式JavaScript框架 构建用户界面:把数据通过某种办法变成用户界面 渐进式:可以 ...

  8. ant-design在 vue 抽屉(drawer)里面嵌套弹出框(modal)出现蒙层遮挡弹框问题

    ant-design在 vue 抽屉(drawer)里面嵌套弹出框(modal)出现蒙层遮挡弹框问题 有时候会遇到这种情况,先打开抽屉,然后再抽屉里打开模态窗,出现模态窗被抽屉的的蒙层遮挡 问题: 可 ...

  9. 【Vue】Vue学习笔记——UI组件库和常用插件

    文章目录 6. UI组件库和常用插件 6.1 Element-ui 6.2 Vue-router 6.2.1 基本用法 6.2.2 跳转 6.2.3 路由嵌套 6.2.4 路由参数传递 6.3 Axi ...

最新文章

  1. SQL优化这么做就对了
  2. android画笔画图(会持续更新完善,欢迎留言提问)
  3. (转)ubuntu 文件系统
  4. to_string()函数----将int类型转换为string型
  5. Linux打tar包排除目录中的某个目录
  6. GameDev.net日报 2010.11.12 要卖了
  7. java监控rabbitMq服务状态,spring cloud 的监控turbine-rabbitmq的示例
  8. 新年开篇,一起成长,送书 7 本!TF + PyTorch方向
  9. python 检测列表中是否有空值,检查python列表中是否已经存在数字
  10. React-组件通信
  11. php与html5怎么弹出消息框,jQuery实现消息弹出框效果
  12. 从零到实现Shiro中Authorization和Authentication的缓存
  13. mysql jdbc8.0驱动包下载_MySQL8.0 connector JAR包的下载位置及JDBC配置
  14. Python遇到的问题:IndentationError: expected an indented block
  15. 使用 k3d 来运行极狐GitLab Runner
  16. 互动课件制作 html,如何实现多图版互动式图片课件的制作
  17. Android 国内阿里云镜像
  18. ArtWork.Conversion.
  19. 百万亚瑟王无法连接服务器请在信号良好的地方重试,乖离性百万亚瑟王无法匹配怎么解决 匹配失败原因和解决方法...
  20. 小米微信无法连接到服务器1-10087,微信无法连接到服务器【搞定方向】

热门文章

  1. Python下使用optparse模块实现对多个文件进行统计【二】
  2. plsql数据库异常---plsql 登录后,提示数据库字符集(AL32UTF8)和客户端字符集(ZHS16GBK)不一致 .
  3. 产品经理有话说!这个报表神器更新了6大功能,绝对亮眼
  4. 逻辑人渴望控制那些让他们感兴趣的东西
  5. 飞鸽传书:不知不觉,时间又没了!
  6. 代码中有的《飞秋》只是一个照面
  7. (飞鸽传书绿色版)网站
  8. C++教程[又能学英文,又能学编程]
  9. 利用pre-compiled headers技术以加速编译速度(一)
  10. 关于arp.exe的一点应用