Vue中的路由
后端路由是指服务器根据路径发送资源
前端路由是指页面根据路径切换不同的组件
- 导入
vue-router.js
到项目目录 - 在导入
vue-router.js
之后,在window
全局对象中就有了一个路由的构造函数VueRouter
- 在使用构造函数
VueRouter
构造对象时可传递一个配置对象- 在配置对象中使用
routes
属性指定匹配规则的数组 routes
属性中的每一项都是一个匹配规则的对象- 匹配规则的对象有两个必须的属性:
path
: 表示监听的路由地址component
: 表示如果路由匹配,则展示component
指定的组件模板对象component
的属性值必须是一个组件的模板对象,不能是组件的引用名称
redirect
: 表示重定向前端路径,修改#
之后的路径,并不会发送请求
- 在配置对象中使用
- 在
Vue
实例中使用router
属性指定构造的路由对象 - 使用
vue-router
提供的<router-view>
元素作为占位符,与路由规则匹配的组件将其替换 - 使用
vue-router
提供的<router-link>
元素作为切换链接- 使用
<router-link>
元素的to
属性指定链接的路径 - 使用
<router-link>
元素的tag
属性指定被渲染成的元素- 默认渲染为
<a>
元素
示例如下:
- 默认渲染为
- 使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./vue-router.js"></script>
</head>
<body>
<div id="app">
<a href="#/login">登录</a>
<a href="#/register">注册</a>
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
<script>
var login = {
template:'<h1>登录组件</h1>'
}
var register = {
template:'<h1>注册组件</h1>'
}
var routerobj = new VueRouter({
routes:[
{path:'/',redirect:'/login'},
{path:'/login',component:login},
{path:'/register',component:register}
]
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
router:routerobj
});
</script>
</body>
</html>
路由样式
- 在当前路由对应的
<router-link>
元素链接上有样式router-link-active
, 可修改里面的样式达到当前路由链接高亮- 也可修改默认的样式类:
- 在使用构造函数
VueRouter
构造对象时配置对象中使用linkActiveClass
属性指定样式名即可修改默认的router-link-active
样式类
例如;
- 在使用构造函数
- 也可修改默认的样式类:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./vue-router.js"></script>
<style type="text/css">
.router-link-active{
color: tomato;
}
.myactive{
color: darkgoldenrod;
}
</style>
</head>
<body>
<div id="app">
<a href="#/login">登录</a>
<a href="#/register">注册</a>
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
<script>
var login = {
template:'<h1>登录组件</h1>'
}
var register = {
template:'<h1>注册组件</h1>'
}
var routerobj = new VueRouter({
routes:[
{path:'/',redirect:'/login'},
{path:'/login',component:login},
{path:'/register',component:register}
],
linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
router:routerobj
});
</script>
</body>
</html>
路由切换动画
- 使用
<transition>
元素将<router-view>
元素包含在内 - 定义过渡样式类
- 使用
<transition>
元素的mode
属性设置过渡的模式
示例如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./vue-router.js"></script>
<style type="text/css">
.router-link-active{
color: tomato;
}
.myactive{
color: darkgoldenrod;
}
.v-enter,.v-leave-to{
opacity: 0;
transform: translateX(150px);
}
.v-enter-active,.v-leave-active{
transition: all 0.4s ease;
}
</style>
</head>
<body>
<div id="app">
<a href="#/login">登录</a>
<a href="#/register">注册</a>
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<transition mode="out-in">
<router-view></router-view>
</transition>
</div>
<script>
var login = {
template:'<h1>登录组件</h1>'
}
var register = {
template:'<h1>注册组件</h1>'
}
var routerobj = new VueRouter({
routes:[
{path:'/',redirect:'/login'},
{path:'/login',component:login},
{path:'/register',component:register}
],
linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
router:routerobj
});
</script>
</body>
</html>
路由规则中传参
- 方式一:
- 给路由传参不需要修改路由规则的
path
属性 - 使用的传参方式为问号传参
- 通过组件对象的
$route
属性中包含参数等信息,通过该属性的query
属性可得到传递的参数
例如:
- 给路由传参不需要修改路由规则的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/login?id=10&name=e">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
<script>
var login = {
template:'<h1>登录组件 ---- {{ $route.query.id + " -- " + $route.query.name }}</h1>',
created(){
console.log(this.$route.query)
}
}
var register = {
template:'<h1>注册组件</h1>'
}
var router = new VueRouter({
routes:[
{path:'/',redirect:'/login'},
{path:'/login',component:login},
{path:'/register',component:register}
],
linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
router
});
</script>
</body>
</html>
- 方式二:
- 路由的匹配规则使用
/:
加参数名的形式传参- 需匹配到每一个
/:
加参数的路径
例如:
- 需匹配到每一个
- 路由的匹配规则使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/login/101/lisi">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>
<script>
var login = {
template:'<h1>登录组件 --- {{ $route.params }}</h1>',
created(){
console.log(this.$route.params)
}
}
var register = {
template:'<h1>注册组件</h1>'
}
var router = new VueRouter({
routes:[
{path:'/',redirect:'/login/104/zhangsan'},
{path:'/login/:id/:name',component:login},
{path:'/register',component:register}
],
linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
router
});
</script>
</body>
</html>
路由的嵌套
- 在匹配规则的对象中使用
children
属性指定子路由- 子路由与其父路由相似,但不同的是
path
属性中无/
- 若
path
以/
开始,则从根路径开始匹配
例如:
- 子路由与其父路由相似,但不同的是
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/account">Account</router-link>
<router-view></router-view>
</div>
<template id="tem1">
<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 login = {
template:'<h1>登录组件</h1>'
}
var register = {
template:'<h1>注册组件</h1>'
}
var account = {
template:'#tem1'
}
var router = new VueRouter({
routes:[
{
path:'/account',
component:account,
children:[{
path:'login',
component:login
},{
path:'register',
component:register
}]
}
// {path:'/account/login/:id/:name',component:login},
// {path:'/account/register',component:register}
],
linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
router
});
</script>
</body>
</html>
命名视图
- 可以在路由的匹配规则的对象中使用
components
属性指定多个组件模板对象 - 将多个的组件模板对象封装为一个对象,使用不同的属性指定相应的一个组件模板对象
- 与每个组件模板对象对应的属性名用于在
<router-view>
元素中的name
属性上 - 根据
<router-view>
元素中的name
属性将其渲染对应组件
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./vue-router.js"></script>
<style type="text/css">
.header{
background-color: lightslategray;
height: 100px;
}
/* .left{
float: left;
} */
/* .main{
float: right;
} */
.container{
display: flex;
height: 800px;
}
h1{
margin: 0;
padding: 0;
}
html,body{
margin: 0;
padding: 0;
}
.left{
background-color: black;
color: cornflowerblue;
flex: 2;
}
.main{
background-color: bisque;
flex: 8;
}
</style>
</head>
<body>
<div id="app">
<router-link to="/account">Account</router-link>
<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:'<h1 class="header">头部</h1>'
}
var left = {
template:'<h1 class="left">侧边栏</h1>'
}
var main = {
template:'<h1 class="main">主页</h1>'
}
var router = new VueRouter({
routes:[
{path:'/',components:{default:header,left:left,main:main}}
],
linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
router
});
</script>
</body>
</html>
数据监听
- 使用
Vue
实例的watch
属性可以监听到data
中数据的改变,并且触发对应的处理函数 watch
属性指定的是一个对象,其中的属性可以是data
中被监听的数据变量名- 若变量名中有
-
,则将此变量名用作属性时需加' '
包含 - 属性值为一个处理函数对象,函数可传参有
newVal
、oldVal
newVal
: 表示当前属性对应的数据监听到改变前的值newVal
: 表示当前属性对应的数据监听到改变后的值
例如:
- 若变量名中有
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="firstname"> +
<input type="text" v-model="lastname"> =
<span>{{ fullname }}</span>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
lastname:'',
firstname:'',
fullname:''
},
methods: {
},
watch:{
firstname:function(newVal,oldVal){
// this.fullname = this.firstname + "-" + this.lastname;
this.fullname = newVal + "-" + this.lastname;
},
lastname:function(newVal,oldVal){
// this.fullname = this.firstname + "-" + this.lastname;
this.fullname = this.firstname + "-" + newVal;
},
}
});
</script>
</body>
</html>
路由监听
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./vue-router.js"></script>
<style type="text/css">
.router-link-active{
color: tomato;
}
.myactive{
color: darkgoldenrod;
}
.v-enter,.v-leave-to{
opacity: 0;
transform: translateX(150px);
}
.v-enter-active,.v-leave-active{
transition: all 0.4s ease;
}
</style>
</head>
<body>
<div id="app">
<a href="#/login">登录</a>
<a href="#/register">注册</a>
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<transition mode="out-in">
<router-view></router-view>
</transition>
</div>
<script>
var login = {
template:'<h1>登录组件</h1>'
}
var register = {
template:'<h1>注册组件</h1>'
}
var routerobj = new VueRouter({
routes:[
{path:'/',redirect:'/login'},
{path:'/login',component:login},
{path:'/register',component:register}
],
linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
router:routerobj,
watch:{
'$route.path':function(newVal,oldVal){
console.log(newVal + " ---- " + oldVal)
}
}
});
</script>
</body>
</html>
计算属性
- 在
Vue
实例中使用computed
属性- 在
computed
中可以定义一些属性,即计算属性 - 计算属性的本质为一个方法,只是使用时将其名称直接当作属性使用的
- 并不将计算属性当作方法调用
- 在
- 计算属性中所用到的
data
中的数据一旦发生变化,就会重新计算该计算属性的值 - 计算属性的求值结果会被缓存,便于下次使用,若该计算属性对应的方法中所用到的数据都未更改过,则其不会重新求值
示例如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="firstname"> +
<input type="text" v-model="lastname"> =
<span>{{ fullname }}</span><br/>
<span>{{ fullname }}</span><br/>
<span>{{ fullname }}</span><br/>
<span>{{ fullname }}</span><br/>
<span>{{ fullname }}</span><br/>
<span>{{ fullname }}</span><br/>
<span>{{ fullname }}</span><br/>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
lastname:'',
firstname:''
},
methods: {
},
computed:{
'fullname':function(){
console.log('run //')
return this.firstname + ' - ' + this.lastname
}
}
});
</script>
</body>
</html>
computed、watch、methods区别
computed
- 计算属性需返回值
- 重在结果数据(依赖的数据都被监听)
- 结果缓存,依赖数据改变则重新计算,主要当作属性使用
watch
- 一般不需要返回值
- 重在更改的数据
- 可看作为
methods
与computed
的结合体
methods
- 表示一个具体操作,主要为业务逻辑