vue 基础-->进阶 教程(3):组件嵌套、组件之间的通信、路由机制
前面的nodejs教程并没有停止更新,因为node项目需要用vue来实现界面部分,所以先插入一个vue教程,以免不会的同学不能很好的完成项目。
本教程,将从零开始,教给大家vue的基础、高级操作、组件封装等,再配合前面的Nodejs后台,实现一个完整的项目。
组件嵌套
在组件中使用components定义子组件,可以定义多个,定义好以后,就可以在组件的模板中使用子组件了。看下面示例:具体解释在注释中
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body> <div id="box">
<aaa></aaa>
</div> <!--模板可以使用 template标签写到外面,然后在 componets里面调用-->
<template id="temA">
<div>
<h3>我是:{{msg}}</h3>
<bbb></bbb> <!-- 调用子组件 -->
</div>
</template> <script>
var vm=new Vue({
el:'#box',
components:{
'aaa':{
data:function(){
return{
msg:'父组件'
}
},
methods:{
test:function(){
alert("我是父组件")
}
},
template:'#temA',/*父组件的模板*/
components:{
'bbb':{
template:"<h3>我是子组件</h3>"
}
}
}
}
})
</script>
</body>
</html>

父子组件之间的通信
使用 v-bind: (或直接用冒号) 传递数据,使用props接收数据,先看如下代码
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body> <div id="box">
<aaa></aaa> <!--父组件的调用-->
</div> <template id="temA"> <!--模板可以使用 template标签写到外面,然后在 componets里面调用-->
<div>
<h3>我是:{{msg}},子集显示 ==>{{msg2.text}}</h3>
<bbb :m1="msg1" :m2="msg2"></bbb> <!--调用子组件,使用 :键名=值(对应父组件data中的值) 去传参数-->
</div>
</template> <script>
var vm=new Vue({
el:'#box',
components:{
'aaa':{
data:function(){
return{
msg:'父组件',
msg1:"父级的共享数据1",
msg2:{ /*父组件往子组件传的一般只不能子集修改,只有传对象格式,子集中就可以修改了,父组件也同时改了*/
text:"父级的共享数据2",
style:{
height:"100px",
background:"orange"
}
}
}
},
methods:{
test:function(){
console.log("父组件的方法已调用");
}
},
template:'#temA',/*当前组件里调用子组件*/
components:{
'bbb':{
props:["m1","m2"], /* 需要使用的数据,使用数组参入 ,和函数的形参很像,然后在调用的地方使用 v-bind传入 */
template:"<div><h3 @click='showMsg'>我是bbb组件,我使用的父级数据 ==>{{m1}},{{m2.text}} </h3></div>",
methods:{
showMsg:function(){
this.m2.text = "值被子组件修改了";
this.$parent.test();
}
} }
}
}
}
})
</script>
</body>
</html>
解释一下数据的传递流程(以msg2为例):在父组件中的数据中有个msg2数据,在模板中调用子组件的时候 以名为 m2 传递给了子组件
,然后在子组件中就可以通过props接收到
,这样在子组件中就可以使用变量 this.m2访问到 父组件的 msg2对应的值了。(如果传的值是对象,则传递引用指针,如果传递的是基本类型,则直接将值传递过去)
运行:
当点击子组件的h3标签,触发子组件的showMsg方法,在方法中,我们通过 this.m2.text改变了父级的msg2.text的值。通过 this.$parent.方法名 可以直接访问父组件里的方法。

点击bbb后

非父子组件之间的通信
上面我们使用props只能解决父子组件之间的通信,当两个兄弟关系的组件,就不能这样传递了
兄弟节点之间需要使用 事件的触发方法 $emit去实现
先看代码:具体解释在注释中
代码中,我们声明了一个独立的空Vue公用实例,用来触发通讯的事件。在a组件中使用 $emit触发事件,在 c组件中使用on监听事件,就可以实现数据的传递了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="box">
<com-a></com-a> <!-- 调用com-a组件 -->
<com-c></com-c><!-- 调用com-c组件 -->
</div>
<script>
var Event=new Vue(); // 声明一个独立的空Vue公用实例,用来触发通讯的事件 var a={
template:'<div><span>我是a组件,我的数据内容是{{msga}}</span><br><input type="button" value="我要发送数据" @click="send"></div>',
data(){
return{
msga:'我是a数据,我要发送给兄弟组件'
}
},
methods:{
send(){
Event.$emit('a-msg',this.msga) //触发前面 Event 公用示例的方法,那么别的地方就可以想办法监听接收这个事件。参数(事件名,传输的值)
}
}
};
var c={
template:"<div><h3>这是C组件</h3><span>我从A里面接受的数据:{{a}}</span></div>",
data(){
return{
a:''
}
},
mounted(){ //这里的mouted表示当组件和页面挂载完成的时候,需要执行的函数
var _this = this; //因为在Event.on内部的this是指向 Event实例的,所以这里,先使用 _this将this存起来,后面就可以使用了。
Event.$on('a-msg',function (a) { //使用on监听事件 a-msg,这样当a组件中使用 emit主动触发了 Event实例的a-msg事件之后,这里就可以接收到
alert('触发了接收');
_this.a = a;
})
}
};
new Vue({
el:'#box',
components:{
'com-a':a,
'com-c':c
}
}) </script> </body>
</html>
当点击发送数据按钮,数据就传输给了c组件。

路由
路由可以让我们在页面中加载不同的模板内容,
使用vue的路由,需要借助vue-router.js
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
我们使用路由配置一个tab切换,点击首页和列表分别显示不同内容,并且点击的时候,url中的路径会发生对应的改变。


代码如下:代码解释在注释中。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="box">
<div>
<router-link to="/home">首页</router-link> <!-- 会被vue识别,自动显示成a标签-->
<router-link to="/List">列表</router-link> <!-- 会被vue识别,自动显示成a标签-->
</div>
<div>
<router-view></router-view> <!-- 点击上面的link标签由,需要显示模板的地方 -->
</div>
</div>
</body>
<script>
/*组件*/
var Home = {
template:"<h3>我是主页的内容</h3>"
};
var List = {
template:"<h3>我是文章列表</h3>"
}; //配置路由
var routerArr=[
{
path:"/home", /* router-link 的 to跳转的地址 */
component:Home /* 路径对应的组件 */
},
{
path:"/List", /* router-link 的 to跳转的地址 */
component:List /* 路径对应的组件 */
},
{path:"*",component:Home} /*其他的所有情况,都跳转到首页*/
]; //生成路由示例
var router= new VueRouter({
routes:routerArr
}); //vue实例
var vm=new Vue({
el:'#box',
data:{},
/* 示例挂载路由 */
router:router
})
</script>
</html>
二级路由:具体解释在注释中
注:
二级路由使用children来配置 ,内部配置和一级路由一样
tab切换中的当前选项标签会自动添加 router-link-active类,我们只需要设置该类的样式,就可以实现当前选中的样式了。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body{
padding: 30px;
}
ul, li{
display: inline-block;
list-style: none;
}
#box a{
text-decoration: none;
color: #2479dc;
padding: 5px 15px;
}
#box .router-link-active{
background: #2479dc;
color: #fff;
}
</style>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="box">
<div>
<router-link to="/home">首页</router-link> <!-- 会被vue识别,自动显示成a标签-->
<router-link to="/List">列表</router-link>
<router-link to="/users">用户</router-link>
</div>
<div>
<router-view></router-view> <!-- 点击上面的link标签由,需要显示模板的地方 -->
</div>
</div> <!-- 模板 temUser -->
<template id="temUser">
<div> <h3>用户信息</h3>
<hr/>
<ul>
<li><router-link to="/users/xiaoming">小明</router-link></li>
<li><router-link to="/users/xiaohong">小红</router-link></li>
</ul>
<div>
<router-view></router-view> <!-- 点击上面的link标签由,需要显示模板的地方 -->
</div>
</div>
</template> </body>
<script>
/*组件*/
var Home = {
template:"<h3>我是主页的内容</h3>"
};
var List = {
template:"<h3>我是文章列表</h3>"
};
//用户
var users = {
template:"#temUser"
}; var xiaoming = {
template:"<h3>我是小明</h3>"
}
var xiaohong = {
template:"<h3>我是小红</h3>"
} //配置路由
var routerArr=[
{
path:"/home", /* router-link 的 to跳转的地址 */
component:Home /* 路径对应的组件 */
},
{
path:"/List", /* router-link 的 to跳转的地址 */
component:List /* 路径对应的组件 */
},
{
path:"/users", /* router-link 的 to跳转的地址 */
component:users, /* 重定向到首页 */
children:[ /* 二级路由使用children来配置 ,内部配置和一级路由一样 */
{path:"xiaoming",component:xiaoming},
{path:"xiaohong",component:xiaohong}
]
},
{path:"*",component:Home} /*其他的所有情况,都跳转到首页*/
]; //生成路由示例
var router= new VueRouter({
routes:routerArr
}); var vm=new Vue({
el:'#box',
data:{},
/* 示例挂载路由 */
router:router
})
</script>
</html>

url参数传递
在配置路由的时候,路径名前面加 冒号,就表示此路径为参数

然后在模板中就可以使用 $route.params去访问到这个值了

完整示例代码如下:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body{
padding: 30px;
}
ul, li{
display: inline-block;
list-style: none;
}
#box a{
text-decoration: none;
color: #2479dc;
padding: 5px 15px;
}
#box .router-link-active{
background: #2479dc;
color: #fff;
}
</style>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="box">
<div>
<router-link to="/home">首页</router-link> <!-- 会被vue识别,自动显示成a标签-->
<router-link to="/List">列表</router-link>
<router-link to="/users">用户</router-link>
</div>
<div>
<router-view></router-view> <!-- 点击上面的link标签由,需要显示的内容 -->
</div>
</div> <template id="temUser">
<div> <h3>用户信息</h3>
<hr/>
<ul>
<li><router-link to="/users/2/xiaoming/哈哈">小明</router-link></li>
<li><router-link to="/users/xiaohong/15">小红</router-link></li>
</ul>
<div>
<router-view></router-view> <!-- 点击上面的link标签由,需要显示的内容 -->
</div>
</div>
</template> </body>
<script>
/*组件*/
var Home = {
template:"<h3>我是主页的内容</h3>"
};
var List = {
template:"<h3>我是文章列表</h3>"
};
//用户
var users = {
template:"#temUser"
}; var xiaoming = {
template:"<h3>我是小明-{{$route.params.sysId}}{{$route.params.Id}}</h3>"
}
var xiaohong = {
template:"<h3>我是小红-{{$route.params.sysId}}</h3>"
} //配置路由
var routerArr=[
{
path:"/home", /* router-link 的 to跳转的地址 */
component:Home /* 路径对应的组件 */
},
{
path:"/List", /* router-link 的 to跳转的地址 */
component:List /* 路径对应的组件 */
},
{
path:"/users", /* router-link 的 to跳转的地址 */
component:users, /* 重定向到首页 */
children:[
{path:":Id/xiaoming/:sysId",component:xiaoming},
{path:"xiaohong/:sysId",component:xiaohong}
]
},
{path:"*",component:Home} /*其他的所有情况,都跳转到首页*/
]; //生成路由示例
var router= new VueRouter({
routes:routerArr
}); var vm=new Vue({
el:'#box',
data:{},
/* 示例挂载路由 */
router:router
})
</script>
</html>
点击 用户 --> 小红 ,然后可以看到我们url中的 "15",就传递到了模板中显示出来了。

补充讲一个概念:槽/slot 用来接收标调用时传入的内部内容
直接上代码,解释在注释中
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
body{
line-height: 30px;
padding: 10px;
}
</style>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body> <div id="box">
<who-h>
<p>插入slot的值</p> <!-- 在组件调用的时候,标签内部的内容,会被放到template中定义的槽slot标签中 -->
<ul>
<li>ssss</li>
<li>ssss</li>
<li>ssss</li>
</ul>
</who-h>
</div> <template id="temp01"> <!-- template 用来定义模板,需要指定一个id -->
<div> <!-- 模板中的内容,只能包裹在唯一一个标签中 (最外层不能有多个标签) -->
<h3>{{msg}}</h3>
<slot></slot> <!-- 用来接收标调用时传入的内部内容-->
</div> </template> <script> var item = Vue.extend({
data:function(){
return {
msg:"示例的值"
}
},
template:'#temp01'
}); var vm = new Vue({
el:"#box",
data:{},
components:{ //可以配置多个内部组件
"who-h":item //组件命名的时候,最好都用引号引起来(当然,单个单词的时候不用也不报错)
}
}) </script> </body>
</html>
显示结果我们可以看到,原来 slot所在的地方被传入的p和ul标签替代了

上面是一个slot的情况,当如果我们要多个slot分开传值,我们就需要给slot指定名字,并且给传入的标签指定slot
示例如下:具体的解释在注释中
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
body{
line-height: 30px;
padding: 10px;
}
</style>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body> <div id="box">
<who-h>
<p slot="slot01">插入slot的值1(p)</p> <!-- 在组件调用的时候,标签内部的内容,会被放到template中定义的槽slot标签中,使用slot属性去指定插入哪个slot,如果不指定slot名,就插入没有名字的slot中 -->
<ul slot="slot02">
<li>插入slot的值2(ul)</li>
</ul>
<span>插入slot的值3(span)</span>
</who-h>
</div> <template id="temp01"> <!-- template 用来定义模板,需要指定一个id -->
<div> <!-- 模板中的内容,只能包裹在唯一一个标签中 (最外层不能有多个标签) -->
<h3>{{msg}}</h3>
<slot></slot> <!-- 用来接收标调用时传入的内部内容-->
<slot name="slot01"></slot>
<slot name="slot02"></slot>
</div> </template> <script> var item = Vue.extend({
data:function(){
return {
msg:"示例的值"
}
},
template:'#temp01'
}); var vm = new Vue({
el:"#box",
data:{},
components:{ //可以配置多个内部组件
"who-h":item //组件命名的时候,最好都用引号引起来(当然,单个单词的时候不用也不报错)
}
}) </script> </body>
</html>
结果如下,三个传入的值 分别插入到了对应的位置

今天就讲到这里,vue就讲这么多,下次更新的时候,就是vue+nodejs的项目了。
关注公众号,博客更新即可收到推送

vue 基础-->进阶 教程(3):组件嵌套、组件之间的通信、路由机制的更多相关文章
- vue 基础-->进阶 教程(2): 指令、组件
第二章 建议学习时间4小时 课程共3章 前面的nodejs教程并没有停止更新,因为node项目需要用vue来实现界面部分,所以先插入一个vue教程,以免不会的同学不能很好的完成项目. 本教程,将从零 ...
- vue 基础-->进阶 教程(2): 指令、自定义指令、组件
第二章 建议学习时间4小时 课程共3章 前面的nodejs教程并没有停止更新,因为node项目需要用vue来实现界面部分,所以先插入一个vue教程,以免不会的同学不能很好的完成项目. 本教程,将从零 ...
- vue 基础-->进阶 教程(1): 基础(数据绑定)
第一章 建议学习时间4小时 课程共3章 前面的nodejs教程并没有停止更新,因为node项目需要用vue来实现界面部分,所以先插入一个vue教程,以免不会的同学不能很好的完成项目. 本教程,将从零 ...
- vuex-- Vue.的中心化状态管理方案(vue 组件之间的通信简化机制)
vuex-- Vue.的中心化状态管理方案(vue 组件之间的通信简化机制) 如果你在使用 vue.js , 那么我想你可能会对 vue 组件之间的通信感到崩溃 .vuex就是为了解决组件通信问题的. ...
- Vue(基础八)_导航守卫(组件内的守卫)
一.前言 主要通过一个例子演示三个钩子的作用: 1.beforeRouteEnter() ...
- Vue.js组件之同级之间的通信
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Vue基础进阶 之 列表过渡
在前面的博客我们一直在操作单个元素的过渡,如果是对多个元素过渡,例如列表,这时就要用到<transition-group>这个组件了: 如何使用:将要操作的列表元素放在<transi ...
- Vue基础进阶 之 过渡效果
进入/离开过渡效果:Vue在插入.更新或移除DOM时,可以设置一些动画效果: 如何使用过渡效果:利用<transition></transition>组件将需要应用的过渡效果的 ...
- Vue基础进阶 之 自定义指令
自定义指令-----钩子函数 自定义指令 除了内置指令,Vue也允许用户自定义指令: 注册指令:通过全局API Vue.directive可以注册自定义指令: 自定义指令的钩子函数: bind: in ...
随机推荐
- 学习笔记:javascript内置对象:数学对象
1.数学对象 -Math 2.对象常用属性 3.常用函数 4.对数值类型数据保留小数的函数
- MySQL的SELECT ...for update
最近的项目中,因为涉及到Mysql数据中乐观锁和悲观锁的使用,所以结合项目和网上的知识点对乐观锁和悲观锁的知识进行总结. 悲观锁介绍 悲观锁是对数据被的修改持悲观态度(认为数据在被修改的时候一定会存在 ...
- 通过js给网页加上水印背景
有些后端管理系统,因为业务逻辑的需要,需要加上水印,下面就是水印方法. function watermark(settings) { debugger; //默认设置 var defaultSetti ...
- RegExp(正则表达式)常用知识点小结
原文地址:→看过来 正则表达式用到的地方很多,但是每次很久不用就全忘光了,每次都要重新看一遍文档,为了节省时间,把它的一些基本要点画总结在一张图片中,这样方便以后查看. PS:细节的东西还是需要看详细 ...
- 单元测试(Spring)
单元测试是指对软件中的最小可测试单元进行的检查和验证,是软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试. 单元测试好处:提高代码质量(实现功能.逻辑 ...
- 细说C#中的系列化与反系列化的基本原理和过程
虽然我们平时都使用第三方库来进行系列化和反系列化,用起来也很方便,但至少得明白系列化与反系列化的基本原理. 注意:从.NET Framework 2.0 开始,系列化格式化器类SoapFormatte ...
- Java中线程总结
本文简要介绍在 Java 世界中, 线程相关知识.主要包含 线程的创建与销毁:线程安全与同步:线程通讯:注意本文没有什么高深新知识,只缘起前段时间在翻看项目代码的时候,发现有些同学对此有诸多误解,故在 ...
- Mac下安装第三方模块报错:‘sqlfront.h‘ file not found的解决办法
1.软件环境: mac环境:10.11.6(15G31) python: 3.6 2.问题: sudo pip install pymssql 后出现下面问题: fatal error: 'sqlfr ...
- 【Netty】UDP广播事件
一.前言 前面学习了WebSocket协议,并且通过示例讲解了WebSocket的具体使用,接着学习如何使用无连接的UDP来广播事件. 二.UDP广播事件 2.1 UDP基础 面向连接的TCP协议管理 ...
- sql备份文件兼容性问题
第一步: 右键需要备份的数据库,选择"属性"