配套源码下载: 传送门
1 Vue生命周期 ☆☆☆
- beforeCreate:Vue实例仅仅完成了自身事件的绑定和生命周期函数的初始化工作,Vue实例中还没有
data
el
methods
相关属性 - created:Vue实例已经初始化了
data
属性和methods
中相关方法 - beforeMount:Vue将
el
中指定作用范围作为模板编译 - mounted:已经将数据渲染到界面中并且已经更新页面
- beforeUpdate:执行这个事件执行时仅仅是Vue实例中
data
数据变化,页面显示的依然是原始数据 - updated:data中数据发生变化,页面中数据也发生了变化 页面中数据已经和
data
中数据一致 - beforeDestroy:Vue中所有数据
methods
componet
都没销毁 - destroyed:Vue实例彻底销毁
// 1.初始化阶段
beforeCreate(){
// 生命周期第1个函数,该函数在执行时Vue实例仅仅完成了自身事件的绑定和生命周期函数的初始化工作
// Vue实例中还没有 data el methods相关属性
console.log("beforeCreate:"+this.msg)
},
created(){
// 生命周期第2个函数,该函数在执行时Vue实例已经初始化了data属性和methods中相关方法
console.log("created:"+this.msg)
},
beforeMount(){
// 生命周期第3个函数,该函数在执行时Vue将El中指定作用范围作为模板编译
console.log("beforeMount:"+this.msg)
},
mounted(){
// 生命周期第4个函数
//该函数在执行过程中,已经将数据渲染到界面中并且已经更新页面
console.log("mounted:"+this.msg)
},
// 2.运行阶段
beforeUpdate(){
// 生命周期第5个函数,
// 该函数是data中数据发生变化时执行这个事件执行时仅仅是Vue实例中data数据变化,页面显示的依然是原始数据
console.log("beforeUpdate-data数据:"+this.msg)
const msg1 = document.querySelector(`h1`).innerText
console.log("beforeUpdate-view数据:"+msg1)
},
updated(){
// 生命周期第6个函数,
// 该函数执行时data中数据发生变化,页面中数据也发生了变化 页面中数据已经和data中数据一致
console.log("Updated-data数据:"+this.msg)
const msg1 = document.querySelector(`h1`).innerText
console.log("Updated-view数据:"+msg1)
},
// 3.销毁阶段
beforeDestroy(){
// 生命周期第7个函数,
// 该函数执行时,Vue中所有数据 methods componet 都没销毁
console.log("开始销毁:"+this.msg)
},
destroyed(){
// 生命周期第8个函数,
// 该函数执行时,Vue实例彻底销毁
console.log("结束销毁:"+this.msg)
}
2 图书管理系统
本项目是前后端分离小Demo,需要使用axios请求后端数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>
<body>
<div id="app">
<div class="container">
<div class="row">
<div class="col-sm-12" style="text-align: center">
<h1>员工列表</h1>
</div>
</div>
<div class="row">
<div class="col-sm-12" style="text-align: center;">
<table class="table table-striped table-bordered table-hover">
<tr>
<th>id</th>
<th>name</th>
<th>author</th>
<th>publish</th>
<th>pages</th>
<th>price</th>
<th>do</th>
</tr>
<tr v-for="(book,index) in books" :key="book.id" :class="index%2===0?'info':'success'">
<td>{{book.id}}</td>
<td>{{book.name}}</td>
<td>{{book.author}}</td>
<td>{{book.publish}}</td>
<td>{{book.pages}}</td>
<td>{{book.price}}</td>
<td>
<a href="javascript:void(0);" @click="queryById(book.id)" class="btn btn-primary btn-sm">修改</a>
<a href="javascript:void(0);" @click="deleteBook(book.id)" class="btn btn-danger btn-sm">删除</a>
</td>
</tr>
</table>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<form>
<div class="form-group">
<label>id</label>
<input type="email" class="form-control" v-model="book.id" readonly>
</div>
<div class="form-group">
<label>name</label>
<input type="text" class="form-control" v-model="book.name">
</div>
<div class="form-group">
<label>author</label>
<input type="text" class="form-control" v-model="book.author">
</div>
<div class="form-group">
<label>publish</label>
<input type="text" class="form-control" v-model="book.publish">
</div>
<div class="form-group">
<label>pages</label>
<input type="text" class="form-control" v-model="book.pages">
</div>
<div class="form-group">
<label>price</label>
<input type="text" class="form-control" v-model="book.price">
</div>
</form>
<button @click="addBook" class="btn btn-info btn-block">新增</button>
<button @click="modifyBook" class="btn btn-success btn-block">修改</button>
</div>
</div>
</div>
</div>
<script src="statics/vue.js"></script>
<script src="statics/axios.js"></script>
<script>
const instance = axios.create({
baseURL:'http://localhost:8081',
timeout:5000,
headers:{'X-Custom-Header': 'foobar'}
})
instance.interceptors.response.use(function (response) {
return response;
},function (error) {
console.log(error)
alert("服务端出现错误,稍后再试!")
})
new Vue({
el:"#app",
data:{
book:{},
books:[]
},
methods:{
addBook(){
instance.post("/book/insert",this.book).then(resp => window.location.reload())
},
deleteBook(bookId){
instance.delete("/book/delete/"+bookId).then(resp => window.location.reload())
},
modifyBook(){
instance.put("/book/modify",this.book).then(resp => window.location.reload())
},
queryById(bookId){
instance.get("/book/get/"+bookId).then(resp => this.book = resp.data)
}
},
created(){
instance.get("/book/getAll").then(resp => this.books = resp.data)
}
})
</script>
</body>
</html>
代码演示:
3 javascript es6常用新特性
3.1 变量声明
var
:存在作用域混乱的问题(不再使用)let
: 用来声明局部变量,作用域严谨const
:用来声明常量,一旦赋值不能修改
注意:
- 定义一个对象
const
,在定义对象时指的是对象的地址不变对象中属性可以改变 - 定义一个数组
const
,在定义数组时指的数组地址不能改变﹑但是数组中元素可以改变
3.2 箭头函数 ☆☆☆
- 当箭头函数没有参数或者参数大于1,必须加入
()
- 当箭头函数只有一个参数时,
()
可以不写 - 当函数体中只有一行代码时,
{}
可以省略不写 - 箭头函数和匿名函数最大区别:箭头函数没有自己的
this
,匿名函数有自己的this
3.3 模板字符串 ☆☆☆
使用反引号写入html代码,方便简洁。
反引号:shift+esc下面那个键
let html = `<div>
<a href="https://www.baidu.com">百度</a>
<div>`
console.log(html)
效果演示:
3.4 对象定义
在对象定义时,如果对象的属性名和变量名一致,写一个即可
例如:创建user对象
let name = "cycyong"
let age = 23
let address = "北京"
let user_1 = {name,age,address}
let user_2= {name:name,age:age,address:address}
console.log("es6语法:"+user_1)
console.log("es5语法:"+user_2)
效果演示:
4 Vue标准开发方式
- Vue推荐开发方式是SPA:Single Page (Web)Apploacation 单页面应用
- 什么是SPA 单页面应用?
- 就是项目中只有一张index.html页面
- 为什么Vue推荐SPA开发方式?
- 引入vue.js
- 在现有页面中创建vue实例对象
- 一个页面只能存在一个vue实例
- 一个应用中只能存在一个Vue实例
- 现有手段遵循SPA会出现什么问题?
- 一个页面的代码会越来越多,不利于后期维护
- 一个页面完成全部业务功能 ,导致页面加载速度慢
5 Components 组件
5.1 为什么引入Components?
为了严格遵守SPA的开发模式!!!
- 组件减少vue根实例的代码量
- 一个组件负责完成项目中的一个功能或者一组功能,实现业务功能隔离
- 组件还能在vue中实现复用
5.2 简单使用
5.2.1 全局组件
全局组件:直接注册vue根实例组件
全局组件注册给Vue实例,日后可以在任意Vue实例的范围内使用该组件
// 定义一个全局组件,参数1:组件名称,参数2:组件的配置对象
Vue.component('login',{
template:`<div><h2>登录</h2> <form action=""></form></div>`,// 书写html代码
})
Vue.component('register',{
template:`<div><h2>注册</h2> <form action=""></form></div>`,// 书写html代码
})
5.2.2 局部组件 ☆☆☆
局部组件:只能在注册组件中使用组件
局部组件注册给对应Vue实例中一个components来完成组件注册,这种方式不会对Vue实例造成累加
new Vue({
el:'#app',
components:{
add:{
template:`<div><h2>用户添加</h2></div>`,
}
}
})
5.2.3 使用组件
<div id="app">
<!--登录-->
<login></login>
<!--注册-->
<register></register>
<!--用户添加-->
<add></add>
</div>
注意:无论使用全局组件还是局都组件都必须在组件template中加入唯一根元素
5.3 定义data、methods、components
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<login></login>
<register></register>
</div>
<script src="statics/vue.js"></script>
<script>
// 全局组件
Vue.component('register',{
template:`<div><h3>用户注册</h3><span>{{msg}}</span></div>`,
data(){
return{
msg:'我是全局组件'
}
}
})
// 局部组件
const login = {
template:`
<div>
<h2>用户登录</h2>
<h2>{{count}}---{{countSqrt}}---{{countSqrt}}</h2>
<button @click="test(10)">点击</button>
<aa></aa>
<register></register>
</div>
`,
data(){
return{
count:0,
msg:"hello vue"
}
},
methods:{
test(count){
this.count+=count;
}
},
computed:{
countSqrt(){
return this.count*this.count
}
},
components:{
aa:{
template: `<div><span>aa组件</span></div>`
}
}
}
new Vue({
el:"#app",
data:{},
components:{
login,
}
})
</script>
</body>
</html>
注意:除了data属性转变成function
之后,其他与Vue的实例对象无太大的差异
5.4 props
作用:props用来给组件传递相应静态数据或者是动态数据的
5.4.1 父组件向子组件传递静态数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<login name="cycyong" age="12"></login>
</div>
<script src="statics/vue.js"></script>
<script>
const login = {
template:`<div><h3>用户登录----{{name}}----{{age}}-----{{child_age}}</h3></div>`,
data(){
return{
child_age:this.age
}
},
// 用来接收父组件给当前组件传递数据
// 注意:props机制接收数据就相当于在自己组件data中声明一个数据
props:['name','age'],
}
new Vue({
el:"#app",
components:{
login,
},
})
</script>
</body>
</html>
总结:
- props机制接收数据就相当于在自己组件data中声明一个数据
- 传递静态数据就是在标签上声明静态数据,
key=value
的形式,然后在组件内部使用props
接收数据才能使用,对应接口的key
即可 - 使用组件时可以在组件上定义多个属性以及对应数据
5.4.2 父组件向子组件传递动态数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="name">
<login :name="name"></login>
</div>
<script src="statics/vue.js"></script>
<script>
const login = {
template: `<div><h3>用户登录----{{name}}</h3></div>`,
props:['name']
}
new Vue({
el:"#app",
data:{
name:'cycyong'
},
components:{
login,
},
})
</script>
</body>
</html>
总结:向子组件传递动态数据,就是在标签上声明动态数据,:key=value
的形式,然后在组件内部使用props
接收数据才能使用,对应接口的key
即可
5.4.3 prop的单向数据流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="count">
<login :count="count"></login>
</div>
<script src="statics/vue.js"></script>
<script>
const login = {
template: `<div>
<h3>用户登录----{{count}}</h3>
<button @click="test">点击</button>
</div>
`,
props:['count'],
methods:{
test(){
this.count++
}
}
}
new Vue({
el:"#app",
data:{
count:0
},
components:{
login,
},
})
</script>
</body>
</html>
单向数据流:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。—摘自官网
运行结果:
5.4.4 父组件向子组件传递事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--@key=value,@传递事件名="父组件中传递事件名"-->
<login name="cycyong" :msg="msg" @aa="testParents"></login>
</div>
<script src="statics/vue.js"></script>
<script>
const login = {
template: `<div>
<h3>用户登录----{{name}}-----{{msg}}</h3>
<button @click="testChild">点我调用父组件某个事件</button>
</div>
`,
props:['name','msg'],
methods:{
testChild(){
console.log('child:我是子组件的方法')
this.$emit('aa')
}
}
}
new Vue({
el:"#app",
data:{
msg:"hello vue"
},
methods:{
testParents(){
console.log('parent:我是父组件的方法')
}
},
components:{
login,
},
})
</script>
</body>
</html>
总结:
- 使用方法:@key=value,@传递事件名=“父组件中传递事件名”
- 在子组件调用方法中加入this.$emit(‘传递事件名’)
代码演示:
5.4.5 子组件通过事件向父组件传递参数
根据上一小节的内容,子组件可以通过事件调用父组件的methods
,那么是否能向父组件传递data
呢?
答案是肯定的!!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--@key=value,@传递事件名="父组件中传递事件名"-->
<login name="cycyong" :msg="msg" @aa="testParents"></login>
</div>
<script src="statics/vue.js"></script>
<script>
const login = {
template: `<div>
<h3>用户登录----{{name}}-----{{msg}}</h3>
<button @click="testChild">点我调用父组件某个事件</button>
</div>
`,
props:['name','msg'],
data(){
return{
count:11111,
}
},
methods:{
testChild(){
console.log('child:我是子组件的方法')
this.$emit('aa',this.count)
}
}
}
new Vue({
el:"#app",
data:{
msg:"hello vue"
},
methods:{
testParents(count){
console.log('parent:我是父组件的方法')
console.log('子组件传递过来的参数:'+count)
}
},
components:{
login,
},
})
</script>
</body>
</html>
代码演示:
5.4.6 slot 插槽
作用:用来扩展现有组件让组件变得更加灵活usb接口
具名插槽:带有名字插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<hr>
<login><span slot="pre">前插槽</span><span slot="next">后插槽</span></login>
<hr>
<span>{{count}}</span>
<login><button slot="pre" @click="test">点我</button></login>
</div>
<script src="statics/vue.js"></script>
<script>
const login = {
template:`
<div>
<slot name="pre"></slot>
<h2>用户登录</h2>
<slot name="next"></slot>
</div> `
}
const app = new Vue({
el:"#app",
data:{
msg:"slot的使用",
count:0,
},
methods:{
test(){
this.count++
}
},
components:{
login,
}
})
</script>
</body>
</html>
代码演示:
6 router 路由
6.1 router 简介
定义: Vue Router 是Vne js 官方路由管理器,它和Vne. js 的核心深度集成,让构建单页面应用变得易如反掌
太官方了!!!
通俗定义:通过使用vne Router 可以将现有vue开发变得更加灵活,他可以根据前端请求url对应在页面中展示。
6.2 router 基本使用
使用步骤:
- 下载vue-roouter.js,并在页面中引入
- 创建路由规则对象,并在Vue实例中注册
- 配置理由规则
- 展示路由组件
<router-view>
- 添加切换路由连接
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<a href="#/login">用户登录</a>
<a href="#/reg">用户注册</a>
<!--显示路由组件标签-->
<router-view></router-view>
</div>
<script src="statics/vue.js"></script>
<script src="statics/vue-router.js"></script>
<script>
const login = {
template: `
<div>
<h3>用户登录</h3>
</div>
`,
}
const reg = {
template: `
<div>
<h3>用户注册</h3>
</div>
`,
}
const notFound = {
template: `
<div>
<h3>404 Not Found</h3>
</div>
`,
}
// 创建路由规则对象
const router = new VueRouter({
//配置路由规则
routes:[
// 默认组件
{
path:'/',
// 重定向
redirect:'/login'
},
// 登录组件
{
path:'/login',
component:login
},
// 注册组件
{
path: '/reg',
component: reg
},
// 404路由(放在最后面)
{
path: '*',
component: notFound
}
]
})
const app = new Vue({
el:"#app",
data:{
msg:"router基本使用"
},
components:{
login,
reg,
notFound
},
//注册路由
router,
})
</script>
</body>
</html>
总结:
- 常用表达:
- 默认路由:
/
- 重定向:
redirect:'path'
- 通配符:
*
,该路由规则一般放在最后一个
- 默认路由:
- 我们可以看到地址栏有很长一串类似乱码的东西,这是哈希路由,在最后面有
#/
代码演示:
6.3 使用router-view 切换路由
使用router-view 切换路由切换路由的方法:
- 路径切换路由
a标签
切换路由链接:需要写一个#
router-view
路径切换路由
- 名称切换路由
router-view
名称切换路由
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<!--1.路径切换路由:根据请求路径变换路由-->
<!--1.1切换路由链接-->
<a href="#/login">用户登录</a>
<a href="#/reg">用户注册</a>
<br>
<!--1.2切换路由标签 router-link 标签必须加入 to属性 to="路由路径"-->
<router-link to="/login">用户登录</router-link>
<router-link to="/reg">用户注册</router-link>
<br>
<!--1.3切换路由标签-->
<router-link :to="{path:'/login'}">用户登录</router-link>
<router-link :to="{path:'/reg'}">用户注册</router-link>
<br>
<!--2.名称切换路由:根据路由对象名称切换路由显示不同组件,根据路由名称切换路由只能使用router-link(推荐使用)-->
<router-link :to="{name:'login'}">用户登录</router-link>
<router-link :to="{name:'reg'}">用户注册</router-link>
<router-view></router-view>
</div>
<script src="statics/vue.js"></script>
<script src="statics/vue-router.js"></script>
<script>
const login = {
template: `
<div>
<h3>用户登录</h3>
</div>
`,
}
const reg = {
template: `
<div>
<h3>用户注册</h3>
</div>
`,
}
const notFound = {
template: `
<div>
<h3>404 Not Found</h3>
</div>
`,
}
const router = new VueRouter({
routes:[
{
path:'/login',
component: login,
name:'login'
},
{
path: '/reg',
component: reg,
name:'reg'
}
]
})
const app = new Vue({
el:"#app",
data:{
msg:"router基本使用之使用router-view切换路由"
},
components:{
login,
reg,
notFound
},
router,
})
</script>
</body>
</html>
6.4 使用JS代码切换路由
this.$route object
当前路由对象
this.$router vueRouter
代表路由管理器对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<!--切换路由 1.通过标签直接切换 2.使用js代码切换-->
<router-link :to="{name:'login'}">用户登录</router-link>
<router-link :to="{name:'reg'}">用户注册</router-link>
<br>
<button @click="login">用户登录</button>
<button @click="reg">用户注册</button>
<router-view></router-view>
</div>
<script src="statics/vue.js"></script>
<script src="statics/vue-router.js"></script>
<script src="statics/axios.js"></script>
<script>
const login = {
template: `
<div>
<h3>用户登录</h3>
</div>
`,
}
const reg = {
template: `
<div>
<h3>用户注册</h3>
</div>
`,
}
const notFound = {
template: `
<div>
<h3>404 Not Found</h3>
</div>
`,
}
const router = new VueRouter({
routes:[
{
path:'/login',
component: login,
name:'login'
},
{
path: '/reg',
component: reg,
name:'reg'
}
]
})
// 解决同一个路由多次切换的报错问题
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function (location){
return originalPush.call(this,location).catch(err => err)
}
const app = new Vue({
el:"#app",
data:{
msg:"router基本使用之使用router-view切换路由"
},
methods:{
login(){
// this.$route object 当前路由对象
// this.$router vueRouter 代表路由管理器对象
this.$router.push({name:'login'})// 切换路由
console.log(this.$route)
},
reg(){
this.$router.push({name:'reg'})
console.log(this.$route)
}
},
components:{
login,
reg,
notFound
},
router,
})
</script>
</body>
</html>
解决同一个路由多次切换的报错问题:实际上并无解决,知识不抛出异常了!!!
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function (location){
return originalPush.call(this,location).catch(err => err)
}
6.5 总结:切换路由两大方法 ☆☆☆
标签方式切换:
1.<a href="#路由地址">
2.<router-link to="路由地址">xxxx</router-link>
3.<router-link :to="{path:'路径地址'}">xxxx</router-link>
4.<router-link :to="{name:'路由名称'}">xxxx</router-link>
JS方式切换
1.this.$router.push('路径地址')
2.this.$router.push({path:'路径地址'})
3.this.$router.push({name:'路由名称'})
6.6 路由传递参数
1.queryString ?
this.$route.query.key
2.restful 路径传递参数 /xx/21this.$route.params.key
1.使用a标签传递参数
<a href="#/login?username=cycyong&password=123456">用户登录</a>
<a href="#/reg/cycyong/123456">用户注册</a>
使用query?形式的传递参数方法,参数在 this.$route.query.key
中
使用restful风格形式传参数,参数在this.$route.params.key
中
2.query方式的其他写法:
<!--query-->
<router-link to="/login?username=cycyong&password=123456">用户登录</router-link>
<router-link :to="{path:'/login?username=cycyong&password=123456'}">用户登录</router-link>
<router-link :to="{path:'/login',query:{username:'cycyong',password:'123456'}}">用户登录</router-link>
<router-link :to="{name:'login',query:{username:'cycyong',password:'123456'}}">用户登录</router-link>
3.restful风格方式的其他写法:
<!--query-->
<router-link :to="{path:'/reg/cycyong/123456'}">用户注册</router-link>
<router-link :to="{name:'reg',params:{username:'cycyong',password:'123456'}}">用户注册</router-link>
注意:使用restful风格传参必须先router定义地址格式:
{
path: '/reg/:username/:password',
component: reg,
name:'reg'
}
6.7 嵌套路由
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<a href="#/users">用户列表</a>
<router-view></router-view>
</div>
</body>
</html>
<template id="users">
<div>
<router-link :to="{name:'userAdd'}">用户添加</router-link>
<table border="1">
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
<th>address</th>
<th>do</th>
</tr>
<tr v-for="user in users">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
<td>{{user.address}}</td>
<td>
<router-link :to="{name:'userEdit',query:{id:user.id}}">修改</router-link>
<a href="#">删除</a>
</td>
</tr>
</table>
<!--展示子路由组件-->
<router-view></router-view>
</div>
</template>
<template id="userAdd">
<div>
<form>
姓名:<input type="text"><br>
年龄:<input type="text"><br>
地址:<input type="text"><br>
</form>
</div>
</template>
<template id="userEdit">
<div>
<form>
ID:<input type="text" v-model="user.id" readonly><br>
姓名:<input type="text" v-model="user.name"><br>
年龄:<input type="text" v-model="user.age"><br>
地址:<input type="text" v-model="user.address"><br>
<input type="submit" value="提交" @click="editUser">
</form>
</div>
</template>
<script src="statics/vue.js"></script>
<script src="statics/vue-router.js"></script>
<script>
<!--数据表格组件-->
const users = {
template: "#users",
data(){
return{
users:[],
}
},
created(){
// 发送axios请求后端数据
// 伪造假数据
this.users = [{id:101,name:'cycyong',age:'22',address:'北京'}]
}
}
const userEdit = {
template:'#userEdit',
data(){
return{
user:{}
}
},
methods:{
editUser(){
// 发送axios请求修改用户
// axios.post("url",this.user).then(res=>{
// this.user = {}
// this.$router.push({name:'users'})
// })
this.$router.push({name:'users'})
}
},
created(){
console.log(this.$route.query.id)
// 发送axios请求
this.user = {id:1,name:'cyc',age:22,address:'北京'}
},
}
const userAdd = {
template:'#userAdd',
}
const router = new VueRouter({
routes:[
{
path:'/users',
component:users,
name:'users',
// 嵌套子组件路由:不能由/开头
// 访问子路由:/user/userAdd
children:[
{
path:'userAdd',
component:userAdd,
name:'userAdd'
},
{
path:'userEdit',
component:userEdit,
name:'userEdit'
},
]
},
]
})
const app = new Vue({
el:'#app',
data:{
msg:'嵌套路由'
},
components:{
users,
userAdd,
userEdit,
},
router
})
</script>
注意:
- 子路由
path
不能由/
开头,访问子路由的路径类似user/userAdd
- 子路由在父路由下的
children
中声明
代码演示: