继续1的学习,咱们知道使用:css
能够把.vue文件的内容解析成组件对象的形式:vue
解析相似以下:webpack
咱们使用es6的语法,把render的回调处理参数使用这种处理:es6
import Vue from 'vue' import App from './App.vue' var app = new Vue({ render:h=>h(App) }).$mount("#app")
显示正常:web
咱们已经学习了如何定义组件,组件一样提供了嵌套功能,也就是组件能够嵌套组件:vue-router
main.js定义一个组件,注册:npm
import Vue from 'vue' import App from './App.vue' // 注册 Vue.component('my-component', { template: '<div>A custom component!</div>' }) var app = new Vue({ render:h=>h(App) }).$mount("#app")
App.vue在组件中嵌套使用:json
<template> <div id="app"> helloworld <my-component></my-component> </div> </template> <script> export default { name: 'app' } </script>
显示正常:babel
对于注册组件的第一个参数,是组件名字,第二个参数也就是组件类型对象,咱们知道能够解析.vue文件为这样的对象,咱们建立:app
myComponent.vue:
<template> <div>A custom component!</div> </template> <script> export default { name: 'myComponent' } </script>
main.js使用es6导入注册:
import Vue from 'vue' import App from './App.vue' import myComponent from './myComponent.vue' Vue.component('my-component', myComponent) var app = new Vue({ render:h=>h(App) }).$mount("#app")
除了使用Vue.component注册一个组件,还能够局部注册,注册在vue新建的实例中:
咱们在注册一个组件,是my-component组件的子组件:
weComponent.vue:
<template> <div> 我是myComponent的儿子 </div> </template> <script> export default { name: 'weComponent' } </script>
main.js注册:
import Vue from 'vue' import App from './App.vue' import myComponent from './myComponent.vue' import weComponent from './weComponent.vue' Vue.component('my-component', myComponent) Vue.component('we-component', weComponent) var app = new Vue({ render:h=>h(App) }).$mount("#app")
myComponent.vue使用:
<template> <div> <div>我是myComponent组件</div> <we-component></we-component> </div> </template> <script> export default { name: 'myComponent' } </script>
vue组件的传值方式就是使用属性的方式,而后在子组件中用props属性接收,不过在组件中data数据的设置必须使用函数的形式,在调用位置使用v-bind:xx绑定属性便可:
myComponent.vue:
<template> <div> <div>我是myComponent组件</div> <we-component v-bind:val1="val1"></we-component> </div> </template> <script> export default { name: 'myComponent', data:function(){ return { val1:"我是小李子" } } } </script>
weComponent.vue子组件接收使用props:
<template> <div> 我是myComponent的儿子 <h3>{{val1}}</h3> </div> </template> <script> export default { name: 'weComponent', props:["val1"] } </script>
一样的子组件接收到父组件的值,父组件中这个值变化时,子组件会自动更新到,咱们能够给父组件加一个方法,修改这个传入子组件的值,在vue中绑定事件使用的是v-on:xx(事件名字)=方法,方法要写在methods属性中,在组件内部,获取data的值只须要this.xx便可!
myComponent.vue:
<template> <div> <div>我是myComponent组件</div> <we-component v-bind:val1="val1"></we-component> <button v-on:click="clickVal">点击修改val1的值</button> </div> </template> <script> export default { name: 'myComponent', data:function(){ return { val1:"我是小李子" } }, methods:{ clickVal:function(){ this.val1=this.val1+"1" } } } </script>
点击一次按钮:
是上一种操做的逆处理,vue为咱们提供了这样的接口,在子组件的this会有一个$emit方法,他的参数就是绑定在调用这个组件位置上定义的事件:
weComponent.vue:
<template> <div> 我是myComponent的儿子 <h3>{{val1}}</h3> <button v-on:click="clickPar">告诉父组件值+2</button> </div> </template> <script> export default { name: 'weComponent', props:["val1"], methods:{ clickPar:function(){ this.$emit("parAdd2") } } } </script>
在父组件自定义这个事件,调用一个对应的方法+2:
myComponent.vue:
<template> <div> <div>我是myComponent组件</div> <we-component v-bind:val1="val1" v-on:parAdd2="clickVal2"></we-component> <button v-on:click="clickVal">点击修改val1的值</button> </div> </template> <script> export default { name: 'myComponent', data:function(){ return { val1:"我是小李子" } }, methods:{ clickVal:function(){ this.val1=this.val1+"1" }, clickVal2:function(){ this.val1=this.val1+"2" } } } </script>
咱们这时候会定义多个组件,分别是:
myComponent.vue
youComponent.vue
loveComponent.vue
myComponent.vue:
<template> <div> {{info}} </div> </template> <script> export default { name: 'myComponent', data:function(){ return { info:"myComponent" } } } </script>
youComponent.vue:
<template> <div> {{info}} </div> </template> <script> export default { name: 'youComponent', data:function(){ return { info:"youComponent" } } } </script>
loveComponent.vue:
<template> <div> {{info}} </div> </template> <script> export default { name: 'loveComponent', data:function(){ return { info:"loveComponent" } } } </script>
main.js注册:
import Vue from 'vue' import App from './App.vue' import myComponent from './myComponent.vue' import youComponent from './youComponent.vue' import loveComponent from './loveComponent.vue' Vue.component('my-component', myComponent) Vue.component('you-component', youComponent) Vue.component('love-component', loveComponent) var app = new Vue({ render:h=>h(App) }).$mount("#app")
App.vue应用:
<template> <div id="app"> <h3>tab切换显示:</h3> <my-component></my-component> <you-component></you-component> <love-component></love-component> </div> </template> <script> export default { name: 'app' } </script>
对于显示隐藏vue为咱们提供了v-if和v-show指令,咱们在data设置对应的值,控制便可:
<template> <div id="app"> <h3>tab切换显示:</h3> <my-component v-if="isshowmy"></my-component> <you-component v-if="isshowyou"></you-component> <love-component v-if="isshowlove"></love-component> </div> </template> <script> export default { name: 'app', data:function(){ return { isshowmy:true, isshowyou:false, isshowlove:false } } } </script>
既然是tab切换,只有内容是不对的,还得有对应的三个菜单,咱们写好他们:
<template> <div id="app"> <h3>tab切换显示:</h3> <ul> <li>my-component</li> <li>you-component</li> <li>love-component</li> </ul> <div> <my-component v-if="isshowmy"></my-component> <you-component v-if="isshowyou"></you-component> <love-component v-if="isshowlove"></love-component> </div> </div> </template> <script> export default { name: 'app', data:function(){ return { isshowmy:true, isshowyou:false, isshowlove:false } } } </script>
咱们要给li加入事件,控制对应显示,咱们最简单就是把data的key作参数传递给定义的方法,修改成true,其余是false:
<template> <div id="app"> <h3>tab切换显示:</h3> <ul> <li v-on:click="tab('isshowmy')">my-component</li> <li v-on:click="tab('isshowyou')">you-component</li> <li v-on:click="tab('isshowlove')">love-component</li> </ul> <div> <my-component v-if="isshowmy"></my-component> <you-component v-if="isshowyou"></you-component> <love-component v-if="isshowlove"></love-component> </div> </div> </template> <script> export default { name: 'app', data:function(){ return { isshowmy:true, isshowyou:false, isshowlove:false } }, methods:{ tab:function(key){ this.isshowmy=false; this.isshowyou=false; this.isshowlove=false; this[key]=true; } } } </script>
其实咱们还有一个小操做,就是但愿地址也对应变化,咱们获取key以后,操做window.location.href=#/xx便可!
看地址变化:
咱们仍是基于上面的例子,咱们此次点击li只是修改地址而已:
咱们知道vue提供了一个watch属性,能够监听某个属性变化,而后作出处理,咱们能够把地址放在data的一个属性中,监听他是否修改,而后在修改显示元素对应的布尔值:
<template> <div id="app"> <h3>tab切换显示:</h3> <ul> <li v-on:click="tab('isshowmy')">my-component</li> <li v-on:click="tab('isshowyou')">you-component</li> <li v-on:click="tab('isshowlove')">love-component</li> </ul> <div> <my-component v-if="isshowmy"></my-component> <you-component v-if="isshowyou"></you-component> <love-component v-if="isshowlove"></love-component> </div> </div> </template> <script> export default { name: 'app', data:function(){ return { url:"", isshowmy:true, isshowyou:false, isshowlove:false } }, watch:{ url:function(newurl){ this.isshowmy=false; this.isshowyou=false; this.isshowlove=false; this[newurl]=true; } }, methods:{ tab:function(key){ window.location.href="#/"+key; this.url=key; } } } </script>
这时候咱们的流程就是点击修改了地址,而后根据地址在去控制对应结构的显示。
在咱们单页开发中,路由是很是重要的,就像上面的例子,咱们若是有不少控制显示隐藏的处理,是很是麻烦的,
修改地址,而后显示对应的结构,就变得清晰明了。
vue-router能够帮助咱们很是出色的解决问题,仍是如上例子的处理,咱们使用vue-router完成咱们的实现,
用vue-router就要有这个依赖,咱们安装vue-router有两种方式:
package.json配置好,
{ "name": "stydy-vue", "description": "study-vue", "version": "1.0.0", "author": "tbd", "private": true, "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, "dependencies": { "vue": "^2.4.4" }, "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-env": "^1.6.0", "cross-env": "^5.0.5", "css-loader": "^0.28.7", "file-loader": "^1.1.4", "vue-loader": "^13.0.5", "vue-template-compiler": "^2.4.4", "webpack": "^3.6.0", "webpack-dev-server": "^2.9.1", "vue-router": "^*" } }
而后执行:
npm install
npm手动安装
npm install vue-router
等待完成便可!
如何终止启动的项目:ctrl+c
路由的引入很是简单:
而后就是简单的配置:
import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import myComponent from './myComponent.vue' import youComponent from './youComponent.vue' import loveComponent from './loveComponent.vue' //路由配置 Vue.use(VueRouter); var routes = [ { path: '/', component: myComponent}, { path: '/youComponent', component: youComponent}, { path: '/loveComponent', component: loveComponent} ] var router = new VueRouter({ routes: routes // (缩写)至关于 routes: routes }) var app = new Vue({ render:h=>h(App) }).$mount("#app")
这时候在对应的地址下,配置了使用的对应组件,而后使用VueRouter帮助生成这个实例,而后应用到vue实例中:
import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import myComponent from './myComponent.vue' import youComponent from './youComponent.vue' import loveComponent from './loveComponent.vue' //路由配置 Vue.use(VueRouter); var routes = [ { path: '/', component: myComponent}, { path: '/youComponent', component: youComponent}, { path: '/loveComponent', component: loveComponent} ] var router = new VueRouter({ routes: routes // (缩写)至关于 routes: routes }) var app = new Vue({ router, render:h=>h(App) }).$mount("#app")
路由为咱们提供了它写好的组件,咱们只要直接使用便可!
<router-link to="/isshowmy">my-component</router-link>
最终会被解析成a标签,href就是to的设置,地址点击以后就会变为#/isshowmy的形式
<router-view></router-view>
会根据的路由配置,匹配好,而后显示对应组件。
App.js:
<template> <div id="app"> <h3>tab切换显示:</h3> <ul> <li><router-link to="/">my-component</router-link></li> <li><router-link to="/youComponent">you-component</router-link></li> <li><router-link to="/loveComponent">love-component</router-link></li> </ul> <div> <router-view></router-view> </div> </div> </template> <script> export default { name: 'app' } </script>
咱们修改咱们的myComponent.vue,加入一个列表,而后跳到详情页面,一会咱们在建立详情页的组件和配置对应路由:
myComponent.vue咱们使用vue提供的v-for指令作循环处理:
<template> <div> {{info}} <ul> <li v-for="(item, index) in list"><a v-bind:href="'#/myDetail?id='+item.id">{{item.title}}</a></li> </ul> </div> </template> <script> export default { name: 'myComponent', data:function(){ return { info:"myComponent", list:[ {id:1,title:"c1111111"}, {id:2,title:"c2222222222"}, {id:3,title:"c33333333"}, {id:4,title:"c4444444"}, {id:5,title:"c55555555"} ] } } } </script>
建立myDetail.vue:
<template> <div> 我是详情页面 </div> </template> <script> export default { name: 'myDetail' } </script>
main.js加入路由配置:
import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import myComponent from './myComponent.vue' import youComponent from './youComponent.vue' import loveComponent from './loveComponent.vue' import myDetail from './myDetail.vue' //路由配置 Vue.use(VueRouter); var routes = [ { path: '/', component: myComponent}, { path: '/youComponent', component: youComponent}, { path: '/loveComponent', component: loveComponent}, { path: '/myDetail', component: myDetail} ] var router = new VueRouter({ routes: routes // (缩写)至关于 routes: routes }) var app = new Vue({ router, render:h=>h(App) }).$mount("#app")
咱们看那一下效果:
点击列表进入详情页面:
咱们在new vue实例的时候使用了路由对象,
那么在任何组件中咱们的this都会有一个$route属性,里面会包含全部路由相关的信息和方法处理,
咱们在详情组件的生命周期函数中打印出这个属性的内容:
myDetail.vue,对于生命周期函数,就是组件渲染的阶段:
<template> <div> 我是详情页面 </div> </template> <script> export default { name: 'myDetail', created: function () { console.log(this.$route) } } </script>
看到打印入下:
在如见中显示这个id很是简单,在组件内获取的话就是this.$route. query .id便可!
<template> <div> 我是详情页面id{{this.$route.query.id}} </div> </template> <script> export default { name: 'myDetail', created: function () { console.log(this.$route) } } </script>
这种处理,咱们要在路由配置进行处理:
import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import myComponent from './myComponent.vue' import youComponent from './youComponent.vue' import loveComponent from './loveComponent.vue' import myDetail from './myDetail.vue' //路由配置 Vue.use(VueRouter); var routes = [ { path: '/', component: myComponent}, { path: '/youComponent', component: youComponent}, { path: '/loveComponent', component: loveComponent}, { path: '/myDetail/:id', component: myDetail} ] var router = new VueRouter({ routes: routes // (缩写)至关于 routes: routes }) var app = new Vue({ router, render:h=>h(App) }).$mount("#app")
在传递位置,咱们就能够用地址的形式了:
myComponent.vue:
<template> <div> {{info}} <ul> <li v-for="(item, index) in list"><a v-bind:href="'#/myDetail/'+item.id">{{item.title}}</a></li> </ul> </div> </template> <script> export default { name: 'myComponent', data:function(){ return { info:"myComponent", list:[ {id:1,title:"c1111111"}, {id:2,title:"c2222222222"}, {id:3,title:"c33333333"}, {id:4,title:"c4444444"}, {id:5,title:"c55555555"} ] } } } </script>
在接收端,咱们看console的结果:
咱们只须要把query改为params便可!
myDetail.vue:
<template> <div> 我是详情页面id{{this.$route.params.id}} </div> </template> <script> export default { name: 'myDetail', created: function () { console.log(this.$route) } } </script>
咱们的
会被解析成a,不过有的时候咱们须要在一个事件里面去跳转,好比登陆操做:
youComponent.vue:
<template> <div> {{info}} <button v-on:click="skip">登陆</button> </div> </template> <script> export default { name: 'youComponent', data:function(){ return { info:"youComponent" } }, methods:{ skip:function(){ this.$router.push("loveComponent") } } } </script>
路由除了提供$route以外,还提供了$router,这里面有对应的跳转方法,咱们调用便可!
这个其实也是很是经常使用的,一个简单的例子,关于咱们页面,这个关于咱们地址是:
#/about
他的下面还有三个页面:
联系方式#/about/phone
信息#/about/info
地址#/about/address
这样就出现了嵌套关系,在关于咱们有一部份内容是公用的,一样点击对于的a会显示不一样的内容,当时你是用tab切换也能够。
嵌套路由的配置和路由配置同样,不过是多一级的设置:
main.js:
import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import myComponent from './myComponent.vue' import youComponent from './youComponent.vue' import loveComponent from './loveComponent.vue' import myDetail from './myDetail.vue' import lovePhone from './lovePhone.vue' import loveInfo from './loveInfo.vue' import loveAddress from './loveAddress.vue' //路由配置 Vue.use(VueRouter); var routes = [ { path: '/', component: myComponent}, { path: '/youComponent', component: youComponent}, { path: '/loveComponent', component: loveComponent, children: [ { path: 'lovePhone', component: lovePhone }, { path: 'loveInfo', component: loveInfo }, { path: 'loveAddress', component: loveAddress } ] }, { path: '/myDetail/:id', component: myDetail} ] var router = new VueRouter({ routes: routes // (缩写)至关于 routes: routes }) var app = new Vue({ router, render:h=>h(App) }).$mount("#app")
loveComponent.vue使用嵌套处理,router-link不用多说,重要的是这里面的<router-view></router-view>,根据配置关系,看到这个二级地址以后会找到他一级的结构,而后找到router-view去渲染:
<template> <div> {{info}} <ul> <li><router-link to="/loveComponent/lovePhone">lovePhone</router-link></li> <li><router-link to="/loveComponent/loveInfo">loveInfo</router-link></li> <li><router-link to="/loveComponent/loveAddress">loveAddress</router-link></li> </ul> <div> <router-view></router-view> </div> </div> </template> <script> export default { name: 'loveComponent', data:function(){ return { info:"loveComponent" } } } </script>
咱们一次建立这三个组件,
lovePhone.vue:
<template> <div> {{info}} </div> </template> <script> export default { name: 'lovePhone', data:function(){ return { info:"lovePhone" } } } </script>
loveInfo:
<template> <div> {{info}} </div> </template> <script> export default { name: 'loveInfo', data:function(){ return { info:"loveInfo" } } } </script>
loveAddress:
<template> <div> {{info}} </div> </template> <script> export default { name: 'loveAddress', data:function(){ return { info:"loveAddress" } } } </script>
咱们进入是没有内容的,其实咱们打算显示出:
咱们在路由配置能够加入重定向处理:
main.js:
import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import myComponent from './myComponent.vue' import youComponent from './youComponent.vue' import loveComponent from './loveComponent.vue' import myDetail from './myDetail.vue' import lovePhone from './lovePhone.vue' import loveInfo from './loveInfo.vue' import loveAddress from './loveAddress.vue' //路由配置 Vue.use(VueRouter); var routes = [ { path: '/', component: myComponent}, { path: '/youComponent', component: youComponent}, { path: '/loveComponent', component: loveComponent, redirect: '/loveComponent/lovePhone', children: [ { path: 'lovePhone', component: lovePhone }, { path: 'loveInfo', component: loveInfo }, { path: 'loveAddress', component: loveAddress } ] }, { path: '/myDetail/:id', component: myDetail} ] var router = new VueRouter({ routes: routes // (缩写)至关于 routes: routes }) var app = new Vue({ router, render:h=>h(App) }).$mount("#app")
咱们也许有这样的需求,好比用户的帐户长时间未操做过时了,咱们在进入目的页面会给用户返回到登陆页面,路由为咱们提供了这样的全局的路由变化监听函数:
main.js:
import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import myComponent from './myComponent.vue' import youComponent from './youComponent.vue' import loveComponent from './loveComponent.vue' import myDetail from './myDetail.vue' import lovePhone from './lovePhone.vue' import loveInfo from './loveInfo.vue' import loveAddress from './loveAddress.vue' //路由配置 Vue.use(VueRouter); var routes = [ { path: '/', component: myComponent}, { path: '/youComponent', component: youComponent}, { path: '/loveComponent', component: loveComponent, redirect: '/loveComponent/lovePhone', children: [ { path: 'lovePhone', component: lovePhone }, { path: 'loveInfo', component: loveInfo }, { path: 'loveAddress', component: loveAddress } ] }, { path: '/myDetail/:id', component: myDetail} ] var router = new VueRouter({ routes: routes // (缩写)至关于 routes: routes }) router.beforeEach(function (to, from, next){ console.log(to,"即将要进入的目标 路由对象"); console.log(from,"当前导航正要离开的路由"); next(); }) var app = new Vue({ router, render:h=>h(App) }).$mount("#app")
在这个函数里咱们必须执行一次next函数,不设置参数就是成功跳转到目的页面,也能够设置参数,这个参数就是要跳转的新位置。