1.组件传值-父组件向子组件传值和data与props的区别
2.组件传值-子组件通过事件调用向父组件传值
3.案例:发表评论。使用ref获取DOM元素和组件引用
4.路由-前端路由和后端路由的概念
5.路由-vue-router的基本使用
6.路由-路由redirect重定向的使用
7.路由-设置选中路由高亮的两种方式
8.路由-为路由切换启动动画
9.路由传参-使用query方式传递参数
10.路由传参-使用params方式传递路由参数
11.路由-使用children属性实现路由嵌套
12.路由-使用命名视图实现经典布局
1.组件传值-父组件向子组件传值和data与props的区别 <--返回目录
父组件向子组件传值
<!DOCTYPE html> <html> <head> <title>标题</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- 导入vue的包 --> <script type="text/javascript" src="vue2.js"></script> <style type="text/css"> div { background-color: #ccc; } /*自定义样式,来控制元素动画样式*/ .my-enter, .my-leave-to { opacity: 0; transform:translateX(150px); } .my-enter-active, /*入场动画的时间段*/ .my-leave-active { /*离场动画的时间段*/ transition: all 0.4s ease; } </style> </head> <body> <div id="app"> <a href="" @click.prevent="comName='com1'">组件1</a> <a href="" @click.prevent="comName='com2'">组件2</a> <!-- 通过mode属性,设置组件切换时的模式,out-in表示上一个组件离场动画后,新组件才开始入场动画--> <transition name="my" mode="out-in"> <!-- 父组件,可以在引用子组件的时候,通过属性绑定的形式,传递数据 注意:定义属性名称全部小写 --> <!-- [Vue tip]: Prop "parentmsg" is passed to component <Anonymous>, but the declared prop name is "parentMsg". Note that HTML attributes are case-insensitive and camelCased props need to use their kebab-case equivalents when using in-DOM templates. You should probably use "parent-msg" instead of "parentMsg". --> <component :is="comName" :parentmsg="msg" @parentshow="show"></component> </transition> </div> <script type="text/javascript"> //创建一个vue实例 var vm = new Vue({ el: '#app', data: { comName: 'com1', msg: "父组件的msg" }, methods: { show() { console.log("调用了父组件的show方法"); } }, components: { com1: { template: '<h1 @click="mymethod">这是子组件1----{{parentmsg}}</h1>', //把父组件传递过来的parentMsg属性,在props数组中定义,这样才能使用该属性 props: ['parentmsg'], methods: { mymethod() { this.$emit('parentshow'); } } }, com2: { template: '<h1>这是子组件2</h1>' } } }); </script> </body> </html>
data与props的区别:
1)子组件中所有props中的数据,都是通过父组件传递给子组件的。数据只是可读
2)子组件data中的数据是自身私有的,数据可读可写
2.组件传值-子组件通过事件调用向父组件传值 <--返回目录
<!DOCTYPE html> <html> <head> <title>标题</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- 导入vue的包 --> <script type="text/javascript" src="vue2.js"></script> <style type="text/css"> div { background-color: #ccc; } /*自定义样式,来控制元素动画样式*/ .my-enter, .my-leave-to { opacity: 0; transform:translateX(150px); } .my-enter-active, /*入场动画的时间段*/ .my-leave-active { /*离场动画的时间段*/ transition: all 0.4s ease; } </style> </head> <body> <div id="app"> <a href="" @click.prevent="comName='com1'">组件1</a> <a href="" @click.prevent="comName='com2'">组件2</a> <!-- 通过mode属性,设置组件切换时的模式,out-in表示上一个组件离场动画后,新组件才开始入场动画--> <transition name="my" mode="out-in"> <!-- 父组件,可以在引用子组件的时候,通过属性绑定的形式,传递数据 注意:定义属性名称全部小写 --> <!-- [Vue tip]: Prop "parentmsg" is passed to component <Anonymous>, but the declared prop name is "parentMsg". Note that HTML attributes are case-insensitive and camelCased props need to use their kebab-case equivalents when using in-DOM templates. You should probably use "parent-msg" instead of "parentMsg". --> <component :is="comName" :parentmsg="msg" @parentshow="show"></component> </transition> <br/> <h1>{{msg}}</h1> </div> <script type="text/javascript"> //创建一个vue实例 var vm = new Vue({ el: '#app', data: { comName: 'com1', msg: "父组件的msg" }, methods: { show(data) { console.log("调用了父组件的show方法---" + data ); this.msg = data; } }, components: { com1: { template: '<h1 @click="mymethod">这是子组件1----{{parentmsg}}</h1>', data: function(){ return { sonmsg: '子组件的msg' } }, //把父组件传递过来的parentMsg属性,在props数组中定义,这样才能使用该属性 props: ['parentmsg'], methods: { mymethod() { this.$emit('parentshow', this.sonmsg);//调用父组件传递过来的方法 } } }, com2: { template: '<h1>这是子组件2</h1>' } } }); </script> </body> </html>
3.案例:发表评论。使用ref获取DOM元素和组件引用 <--返回目录
案例:添加评论部分是子组件;父组件对所有评论进行列表展示。评论保存在本地存储localStorage
<!DOCTYPE html> <html> <head> <title>标题</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- 导入vue的包 --> <script type="text/javascript" src="vue2.js"></script>
<link rel="stylesheet" type="text/css" href="bootstrap.min.css"> </head> <body> <div id="app"> <com1></com1> <div class="container"> <ul class="list-group"> <li class="list-group-item" v-for="item in list" :key="item.id"> <span class="badge">{{item.user}}</span> {{item.comments}} </li> </ul> </div> </div> <template id="temp1"> <div class="container"> <div class="row"> <div class="col-md-3"></div> <div class="col-md-6"> <form> <div class="form-group"> <label for="user">用户名</label> <input type="text" name="user" placeholder="输入用户名" class="form-control" v-model="user"> </div> <div class="form-group"> <label for="comments">评论</label> <input type="text" name="comments" placeholder="输入评论" class="form-control" v-model="comments"> </div> <button class="btn btn-primary" @click="postCommets">发表评论</button> </form> </div><!-- /.col-md-6 --> </div><!-- /.row --> </div><!-- /.container --> </template> <script type="text/javascript"> //创建一个vue实例 var vm = new Vue({ el: '#app', data: { list: [] }, methods: { loadComments() { var list = JSON.parse(localStorage.getItem("cmts") || '[]'); this.list = list; } }, created() { this.loadComments(); }, components: { com1: { template: '#temp1', data(){ return { user: '', comments: '' } }, methods: { postCommets() { var obj = {id:Date.now(), user: this.user, comments: this.comments}; var list = JSON.parse(localStorage.getItem("cmts") || '[]'); list.unshift(obj); localStorage.setItem("cmts", JSON.stringify(list)); this.user = ''; this.comments = ''; } } } } }); </script> </body> </html>
// 问题1:我这个案例里面不需要将父组件的loadComments()方法传递给子组件;点击发表按钮后,评论列表自动更新。
// 问题2:我没有手动给输入框注册enter键盘事件,但是也有这个功能,猜测是bootstrap本身自带的。
使用ref获取DOM元素和组件引用
// vue获取dom元素 <!DOCTYPE html> <html> <head> <title>vue获取dom元素</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- 导入vue的包 --> <script type="text/javascript" src="vue2.js"></script> </head> <body> <div id="app"> <input type="button" value="获取h3标签里面的文本" @click="getEle"> <h3 ref="h3Ele">这是一个h3标签</h3> </div> <script type="text/javascript"> //创建一个vue实例 var vm = new Vue({ el: '#app', data: { }, methods: { getEle() { // this.$refs.h3Ele:得到一个原生DOM对象 alert(this.$refs.h3Ele.innerText); } } }); </script> </body> </html> // vue获取子组件 <!DOCTYPE html> <html> <head> <title>vue获取dom元素</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- 导入vue的包 --> <script type="text/javascript" src="vue2.js"></script> <!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> --> </head> <body> <div id="app"> <input type="button" value="获取h3标签里面的文本" @click="getEle"> <com1 ref="com1ref"></com1> </div> <script type="text/javascript"> //创建一个vue实例 var vm = new Vue({ el: '#app', data: { }, methods: { getEle() { console.log(this.$refs.com1ref.sonmsg); this.$refs.com1ref.show(); } }, components: { com1: { template: '<div></div>', data() { return { sonmsg: '子组件的msg' } }, methods: { show() { console.log("调用子组件的show方法:" + this.sonmsg); } } } } }); </script> </body> </html>
4.路由-前端路由和后端路由的概念 <--返回目录
* 后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上的资源
* 前端路由:对应单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,
同时,hash有一个特点:HTTP请求中不会包含hash相关的内容。所以,单页面程序中页面跳转主要用hash实现
* 在单页面应用程序中,这种通过hash改变类切换页面的方式,称做前端路由
* 路由:在URL中采用#号来作为当前视图的地址,改变#号后的参数,页面并不会重载。
* 单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,
是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。
5.路由-vue-router的基本使用 <--返回目录
<!DOCTYPE html> <html> <head> <title>vue获取dom元素</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- 导入vue.js --> <script type="text/javascript" src="vue2.js"></script> <!-- 安装 vue-router 路由模块 --> <script type="text/javascript" src="vue-router.js"></script> </head> <body> <div id="app"> <h1>Hello App!</h1> <p> <!-- 使用 router-link 组件来导航. --> <!-- 通过传入 `to` 属性指定链接. --> <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --> <router-link to="/login">Go to login</router-link> <router-link to="/register">Go to register</router-link> <!-- 下面的方式也可以,但是不推荐注意使用 --> <a href="#/login">登录</a> <a href="#/register">注册</a> </p> <!-- 路由出口 --> <!-- 路由匹配到的组件将渲染在这里 --> <router-view></router-view> </div> <script type="text/javascript"> // 组件的模板对象 var login = { template: '<h1>登录组件</h1>' }; var register = { template: '<h1>注册组件</h1>' }; // 创建一个路由对象 var routerObj = new VueRouter({ routes: [ // 路由匹配规则 {path: '/login', component: login}, {path: '/register', component: register} ] }); // 创建一个vue实例 var vm = new Vue({ el: '#app', data: { }, methods: { }, //将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件 router: routerObj }); </script> </body> </html>
6.路由-路由redirect重定向的使用 <--返回目录
routes: [ // 路由匹配规则
{path: '/', redirect: '/login'},
{path: '/login', component: login},
{path: '/register', component: register}
]
7.路由-设置选中路由高亮的两种方式 <--返回目录
// 第一种方式
<style type="text/css"> .router-link-active { // vue-router默认的 color: red; background-color: #ccc; } </style>
// 设置链接激活时使用的CSS类名。默认值可以通过路由的构造选项linkActiveClass来全局配置。
var routerObj = new VueRouter({ routes: [ // 路由匹配规则 {path: '/', redirect: '/login'}, {path: '/login', component: login}, {path: '/register', component: register} ], linkActiveClass: 'myActive' }); /*修改链接激活使用的CSS类名:myActive*/ .myActive { color: #fff; background-color: #ff3300; }
8.路由-为路由切换启动动画 <--返回目录
/*自定义样式,来控制元素动画样式*/ .my-enter, .my-leave-to { opacity: 0; transform:translateX(150px); } .my-enter-active, /*入场动画的时间段*/ .my-leave-active { /*离场动画的时间段*/ transition: all 0.4s ease; } <!-- 路由匹配到的组件将渲染在这里 --> <transition mode="out-in" name="my"> <router-view></router-view> </transition>
9.路由传参-使用query方式传递参数 <--返回目录
<router-link to="/login?id=10">Go to login</router-link> var login = { template: '<h1>登录组件---{{$route.query.id}}</h1>' };
10.路由传参-使用params方式传递路由参数 <--返回目录
<router-link to="/register/20">Go to register</router-link> var register = { template: '<h1>注册组件---{{$route.params.id}}</h1>' }; // 创建一个路由对象 var routerObj = new VueRouter({ routes: [ // 路由匹配规则 {path: '/', redirect: '/login'}, {path: '/login', component: login}, {path: '/register/:id', component: register} ], linkActiveClass: 'myActive' });
11.路由-使用children属性实现路由嵌套 <--返回目录
<!DOCTYPE html> <html> <head> <title>使用children属性实现路由嵌套</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- 导入vue.js --> <script type="text/javascript" src="vue2.js"></script> <!-- 安装 vue-router 路由模块 --> <script type="text/javascript" src="vue-router.js"></script> <style type="text/css"> /*链接激活默认使用的CSS类名:router-link-active*/ .router-link-active { color: red; background-color: #ccc; } /*修改链接激活使用的CSS类名:myActive*/ .myActive { color: #fff; background-color: #ff3300; } /*自定义样式,来控制元素动画样式*/ .my-enter, .my-leave-to { opacity: 0; transform:translateX(150px); } .my-enter-active, /*入场动画的时间段*/ .my-leave-active { /*离场动画的时间段*/ transition: all 0.4s ease; } .parent { border:1px dashed #000; width: 300px; height: 500px; } </style> </head> <body> <div id="app"> <h1>Hello App!</h1> <p> <!-- 使用 router-link 组件来导航. --> <!-- 通过传入 `to` 属性指定链接. --> <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --> <router-link to="/account">go to account</router-link> </p> <!-- 路由出口,路由匹配到的组件将渲染在这里 --> <transition mode="out-in" name="my"> <router-view class="parent"></router-view><!-- 给父组件留的坑 --> </transition> </div> <template id="temp"> <div> <h2>account--父组件</h2> <router-link to="/account/login">登陆</router-link> <router-link to="/account/register">注册</router-link> <router-view></router-view><!-- 给子组件留的坑 --> </div> </template> <script type="text/javascript"> // 组件的模板对象 var account = { template: '#temp' }; var login = { template: '<h1>login组件</h1>' }; var register = { template: '<h1>register组件</h1>' }; // 创建一个路由对象 var routerObj = new VueRouter({ routes: [ // 路由匹配规则 //{path: '/', redirect: '/account'}, {path: '/account', component: account, children: [ {path: 'login', component: login}, {path: 'register', component: register} ]} ], linkActiveClass: 'myActive', }); // 创建一个vue实例 var vm = new Vue({ el: '#app', data: { }, methods: { }, //将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件 router: routerObj }); </script> </body> </html>
12.路由-使用命名视图实现经典布局 <--返回目录
<!DOCTYPE html> <html> <head> <title>使用命名视图实现经典布局</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- 导入vue.js --> <script type="text/javascript" src="vue2.js"></script> <!-- 安装 vue-router 路由模块 --> <script type="text/javascript" src="vue-router.js"></script> <style type="text/css"> .header { background-color: #abc; height: 80px; } .container { display: flex; height: 600px; } .left { flex: 2; background-color: #ccc; } .main { flex: 8; background-color: blue; } body { margin: 0; padding: 0; } h1 { margin: 0; padding: 0; font-size: 16px; } </style> </head> <body> <div id="app"> <!-- 路由出口,路由匹配到的组件将渲染在这里 --> <router-view class="header"></router-view> <div class="container"> <router-view name="left" class="left"></router-view> <router-view name="main" class="main"></router-view> </div> </div> <script type="text/javascript"> // 组件的模板对象 var header = { template: '<h1>header组件</h1>' }; var left = { template: '<h1>left组件</h1>' }; var main = { template: '<h1>main组件</h1>' }; // 创建一个路由对象 var routerObj = new VueRouter({ routes: [ // 路由匹配规则 {path: '/', components: { 'default': header, 'left': left, 'main': main }} ] }); // 创建一个vue实例 var vm = new Vue({ el: '#app', data: { }, methods: { }, //将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件 router: routerObj }); </script> </body> </html>