后端路由: 对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源;
前端路由: 对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;
在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由);
<script src="./lib/vue-router-2.7.0.js"></script>
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
Vue.extend
创建组件 var login = Vue.extend({
template: '登录组件
'
});
// 4.2 使用 Vue.extend 来创建注册组件
var register = Vue.extend({
template: '注册组件
'
});
var router = new VueRouter({
routers: [
{ path: '/login', component: login },
{ path: '/register', component: register }
]
});
var vm = new Vue({
el: '#app',
router: router // 使用 router 属性来使用路由规则
});
完整代码:
<div id="app">
//router-link 默认渲染为一个a 标签
<router-link to="/login" tag="span">登录</router-link>
<router-link to="/register">注册</router-link>
//这是 vue-router 提供的元素,专门用来 当作占位符的,将来,路由规则,匹配到的组件,就会展示到这个 router-view 中去
//可以把 router-view 认为是一个占位符
<transition mode="out-in">
<router-view></router-view>
</transition>
</div>
<script>
// 组件的模板对象
var login = {
template: '登录组件
'
}
var register = {
template: '注册组件
'
}
// 创建一个路由对象, 当 导入 vue-router 包之后,在 window 全局对象中,就有了一个 路由的构造函数,叫做 VueRouter
// 在 new 路由对象的时候,可以为 构造函数,传递一个配置对象
var routerObj = new VueRouter({
// route // 这个配置对象中的 route 表示 【路由匹配规则】 的意思
routes: [ // 路由匹配规则
// 每个路由规则,都是一个对象,这个规则对象,身上,有两个必须的属性:
// 属性1 是 path, 表示监听 哪个路由链接地址;
// 属性2 是 component, 表示,如果 路由是前面匹配到的 path ,则展示 component 属性对应的那个组件
// 注意: component 的属性值,必须是一个 组件的模板对象, 不能是 组件的引用名称;
// { path: '/', component: login },
{ path: '/', redirect: '/login' }, // 这里的 redirect 和 Node 中的 redirect 完全是两码事
{ path: '/login', component: login },
{ path: '/register', component: register }
],
// linkActiveClass: 'myactive'
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
router: routerObj // 将路由规则对象,注册到 vm 实例上,用来监听 URL 地址的变化,然后展示对应的组件
});
</script>
{ path: '/register/:id', component: register }
this.$route.params
来获取路由中的参数:var register = Vue.extend({
template: '注册组件 --- {{this.$route.params.id}}
'
});
完整代码:
<div id="app">
// 如果在路由中,使用 查询字符串,给路由传递参数,则 不需要修改 路由规则的 path 属性
<router-link to="/login?id=10&name=zs">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
<script>
var login = {
template: '登录 --- {{ $route.query.id }} --- {{ $route.query.name }}
',
data(){
return {
msg: '123'
}
},
created(){ // 组件的生命周期钩子函数
// console.log(this.$route)
// console.log(this.$route.query.id)
}
}
var register = {
template: '注册
'
}
var router = new VueRouter({
routes: [
{ path: '/login', component: login },
{ path: '/register', component: register }
]
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
// router: router
router
});
</script>
<div id="app">
//如果在路由中,使用 查询字符串,给路由传递参数,则 不需要修改 路由规则的 path 属性
<router-link to="/login/12/ls">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
<script>
var login = {
template: '登录 --- {{ $route.params.id }} --- {{ $route.params.name }}
',
data(){
return {
msg: '123'
}
},
created(){ // 组件的生命周期钩子函数
console.log(this.$route.params.id)
}
}
var register = {
template: '注册
'
}
var router = new VueRouter({
routes: [
{ path: '/login/:id/:name', component: login },
{ path: '/register', component: register }
]
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
// router: router
router
});
</script>
children
属性实现路由嵌套<div id="app">
<router-link to="/account">Account</router-link>
<router-view></router-view>
</div>
<template id="tmpl">
<div>
<h1>这是 Account 组件</h1>
<router-link to="/account/login">登录</router-link>
<router-link to="/account/register">注册</router-link>
<router-view></router-view>
</div>
</template>
<script>
// 组件的模板对象
var account = {
template: '#tmpl'
}
var login = {
template: '登录
'
}
var register = {
template: '注册
'
}
var router = new VueRouter({
routes: [
{
path: '/account',
component: account,
// 使用 children 属性,实现子路由,同时,子路由的 path 前面,不要带 / ,否则永远以根路径开始请求,这样不方便我们用户去理解URL地址
children: [
{ path: 'login', component: login },
{ path: 'register', component: register }
]
}
]
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
router
});
</script>
<div id="app">
<router-view></router-view>
<div class="container">
<router-view name="left"></router-view>
<router-view name="main"></router-view>
</div>
</div>
<script>
var header = {
template: 'Header头部区域
'
}
var leftBox = {
template: 'Left侧边栏区域
'
}
var mainBox = {
template: 'mainBox主体区域
'
}
// 创建路由对象
var router = new VueRouter({
routes: [
/* { path: '/', component: header },
{ path: '/left', component: leftBox },
{ path: '/main', component: mainBox } */
{
path: '/', components: {
'default': header,
'left': leftBox,
'main': mainBox
}
}
]
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
router
});
</script>
<style>
html,
body {
margin: 0;
padding: 0;
}
.header {
background-color: orange;
height: 80px;
}
h1 {
margin: 0;
padding: 0;
font-size: 16px;
}
.container {
display: flex;
height: 600px;
}
.left {
background-color: lightgreen;
flex: 2;
}
.main {
background-color: lightpink;
flex: 8;
}
</style>
watch
属性的使用考虑一个问题:想要实现 名
和 姓
两个文本框的内容改变,则全名的文本框中的值也跟着改变;(用以前的知识如何实现???)
data
中属性的改变: <div id="app">
<input type="text" v-model="firstname"> +
<input type="text" v-model="lastname"> =
<input type="text" v-model="fullname">
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
firstname: '',
lastname: '',
fullname: ''
},
methods: {},
watch: { // 使用这个 属性,可以监视 data 中指定数据的变化,然后触发这个 watch 中对应的 function 处理函数
'firstname': function (newVal, oldVal) {
// console.log('监视到了 firstname 的变化')
// this.fullname = this.firstname + '-' + this.lastname
// console.log(newVal + ' --- ' + oldVal)
this.fullname = newVal + '-' + this.lastname
},
'lastname': function (newVal) {
this.fullname = this.firstname + '-' + newVal
}
}
});
</script>
<div id="app">
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
<script>
var login = Vue.extend({
template: '登录组件
'
});
var register = Vue.extend({
template: '注册组件
'
});
var router = new VueRouter({
routes: [
{ path: "/login", component: login },
{ path: "/register", component: register }
]
});
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
router: router,
watch: {
'$route': function (newVal, oldVal) {
if (newVal.path === '/login') {
console.log('这是登录组件');
}
}
}
});
</script>
computed
计算属性的使用getter
的计算属性:<div id="app">
<input type="text" v-model="firstName"> +
<input type="text" v-model="lastName"> =
<span>{{fullName}}</span>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
firstName: 'jack',
lastName: 'chen'
},
methods: {},
computed: { // 计算属性; 特点:当计算属性中所以来的任何一个 data 属性改变之后,都会重新触发 本计算属性 的重新计算,从而更新 fullName 的值
fullName() {
return this.firstName + ' - ' + this.lastName;
}
}
});
</script>
getter
和setter
的计算属性:<div id="app">
<input type="text" v-model="firstName">
<input type="text" v-model="lastName">
//点击按钮重新为 计算属性 fullName 赋值
<input type="button" value="修改fullName" @click="changeName">
<span>{{fullName}}</span>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
firstName: 'jack',
lastName: 'chen'
},
methods: {
changeName() {
this.fullName = 'TOM - chen2';
}
},
computed: {
fullName: {
get: function () {
return this.firstName + ' - ' + this.lastName;
},
set: function (newVal) {
var parts = newVal.split(' - ');
this.firstName = parts[0];
this.lastName = parts[1];
}
}
}
});
</script>
watch
、computed
和methods
之间的对比computed
属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;methods
方法表示一个具体的操作,主要书写业务逻辑;watch
一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是computed
和methods
的结合体;hash模式: 在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash
读取;
特点: hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
history模式: history采用HTML5的新特性;且提供了两个新方法:pushState()
,replaceState()
可以对浏览器历史记录栈进行修改,以及popState
事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是 app 依赖的页面。”