需求:点击左边列表栏显示相应的页面,实现数据的增删改查
1、导入样式
这里使用的是现成的素材
安装 bootstrap 固定版本
npm i bootstrap@3.3.7
安装完成之后 ,在入口处引入 js 文件
import "./../node_modules/bootstrap/dist/css/bootstrap.css"; // 引入
import "./assets/index.css"; // 引入index.css
2、设计组件
页面可以分为三个组件来完成
设计头部组件
<template>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#/">Vue 实践</a>
</div>
</div>
</nav>
</template>
<script>
export default {
}
</script>
<style>
</style>
设计左边列表显示组件
<template>
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<router-link tag="li" to="/1">
<a href="#">1</a>
</router-link>
<router-link tag="li" to="/2">
<a href="#">2</a>
</router-link>
<router-link tag="li" to="/3">
<a href="#">3</a>
</router-link>
</ul>
</div>
</template>
<script>
export default {};
</script>
<style>
</style>
注意:
- 添加 tag 属性后,对应对应生成
<li></li>
标签
参考:https://segmentfault.com/q/1010000015169230
- 因为要使用路由实现页面的改变,所以使用 router-link
设计右边菜单组件
<template>
<div>
<h2 class="sub-header">Hero List</h2>
<a class="btn btn-success" href="/#add">Add</a>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>id</th>
<th>姓名</th>
<th>性别</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>
<a href="javascript:;" >编辑</a>
<a href="javascript:;" @click='deleteI(l.id)'>删除</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
export default {
data(){
},
}
</script>
<style>
</style>
3、使用组件
<template>
<div id="app">
<header-com></header-com>
<div class="container-fluid">
<div class="row">
<list-com></list-com>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<router-view></router-view>
</div>
</div>
</div>
</div>
</template>
<script>
import headerCom from './components/header'
import listCom from './components/list'
import menuCom from './components/menu'
export default {
name: 'App',
components: {
headerCom,
listCom,
menuCom
}
}
</script>
<style>
</style>
注意:
- 这个位置应该是要放右边菜单组件,但是考虑到要通过路由来实现页面的改变,所以放上了路由试图
4、设计功能
路由功能
- 安装路由模块
cnpm i vue-router
- 引用 router
import VueRouter from 'vue-router'
- 使用 router
Vue.use(VueRouter)
- 设计路由表
import firstlist from '../components/menu.vue'
import twolist from '../components/twolist.vue'
import threelist from '../components/threelist.vue'
import add from '../components/add.vue'
import edit from '../components/edit.vue'
const routes = [
{
path: '/',
redirect: '/1'
},
{
path: '/1',
component: firstlist
},
{
path: '/2',
component: twolist
},
{
path: '/3',
component: threelist
},
{
path: '/add',
component: add
},
{
path: '/edit/:id',
component: edit
}
]
const router = new VueRouter({
linkActiveClass: "active",
routes: routes
})
- router 加入实例
new Vue({
store,
render: h => h(App),
router
}).$mount('#app')
- 加入承载视图
<template>
<div id="app">
<header-com></header-com>
<div class="container-fluid">
<div class="row">
<list-com></list-com>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<router-view></router-view>
</div>
</div>
</div>
</div>
</template>
提取路由模块
把路由业务抽取到 router.js
步骤:
- 引入vue
- 在最后一行把 router 对象暴露出去
- 在 main.js 中引入 router.js
import Vue from 'vue'
import VueRouter from 'vue-router'// 引用router
Vue.use(VueRouter) // 使用router
import firstlist from '../components/menu.vue'
import twolist from '../components/twolist.vue'
import threelist from '../components/threelist.vue'
import add from '../components/add.vue'
import edit from '../components/edit.vue'
const routes = [
{
path: '/',
redirect: '/1'
},
{
path: '/1',
component: firstlist
},
{
path: '/2',
component: twolist
},
{
path: '/3',
component: threelist
},
{
path: '/add',
component: add
},
{
path: '/edit/:id',
component: edit
}
]
const router = new VueRouter({
linkActiveClass: "active",
routes: routes
})
//导出router
export default router
import router from './components/router'
列表渲染
当点击左边侧栏时,右边列表显示相应的信息
这里使用的是 json-server 模拟服务器的情况
- 安装 axios 插件
cnpm i axios
- 引入 axios
import axios from "axios"
- 定义数据
data(){
return{
list:[]
}
},
- 请求列表的方法封装
showDate(){
axios.get('http://localhost:3000/heroes').then((rep)=>{
this.list=rep.data
}).catch((er)=>{
console.log(er)
});
},
- 实例完成事件
还要定义方法的触发时间,当匹配到路由,跳转到列表页面时,触发函数,需要使用到钩子函数 mounted
mounted(){
this.showDate()
}
- 根据数据渲染列表
发送请求拿到数据后,还要在页面做相应的渲染
<template>
<div>
<h2 class="sub-header">Hero List</h2>
<a class="btn btn-success" href="/#add">Add</a>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>id</th>
<th>姓名</th>
<th>性别</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for='l in list' :key='l.id'>
<td>{{l.id}}</td>
<td>{{l.name}}</td>
<td>{{l.gender}}</td>
<td>
<a href="javascript:;" >编辑</a>
<a href="javascript:;">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
删除功能
当点击操作栏的删除按钮时,需要发送相应的请求进行删除
- 注册删除事件
<a href="javascript:;" @click='deleteI(l.id)'>删除</a>
- 定义删除方法
deleteI(id){
if(confirm('是否要删除')){
axios.delete('http://localhost:3000/heroes/'+id).then((rep)=>{
if(rep.status == 200){
this.showDate()
}
}).catch(error=>{
console.log(error)
})
}
}
注意:
- 因为删除需要 id 所以定义删除方法的时候 把 id 传进去
- 删除前一定要再次询问
- 删除请求完成后,需要判断删除情况
- 删除完成后,需要再次回到显示列表
新增功能
点击新增按钮时,首先需要跳转到新增页面
- 增加匹配路由
{
path: '/add',
component: add // 引入组件 配置路由
},
- 添加 hash 以对应路由表
<a class="btn btn-success" href="/#add">Add</a>
- 添加页面
<template>
<div>
<h2 class="sub-header">Add 1</h2>
<form>
<div class="form-group">
<label for="exampleInputEmail1">姓名</label>
<input
type="text"
class="form-control"
placeholder="请输入姓名"
/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">性别</label>
<input
type="text"
class="form-control"
placeholder="请输入性别"
/>
</div>
<button type="submit" class="btn btn-success">提交</button>
</form>
</div>
</template>
- v-model 绑定输入框
<input
type="text"
class="form-control"
v-model="formData.name"
placeholder="请输入姓名"
/>
<input
type="text"
class="form-control"
v-model="formData.gender"
placeholder="请输入性别"
/>
//1.添加数据
data() {
return {
// 定义一个数据对象 存储 姓名和性别
formData: {
name: "",
gender: "",
},
};
},
- 新增添加事件
输入框输入完毕后,点击确定按钮需要出发相应事件
<button type="submit" @click="addI" class="btn btn-success">提交</button>
addI() {
if (this.formData.name && this.formData.gender) {
axios
.post("http://localhost:3000/heroes/", this.formData)
.then((rep) => {
if (rep.status == 201) {
this.$router.push({
path: "/",
});
} else {
alert("添加失败");
}
});
} else {
alert("输入为空");
}
},
注意:
- 需要判断输入框是否为空
- 请求完成后,需要判断是否删除成功
- 使用编程式导航完成路由功能,跳转到列表页面
编辑功能
添加编辑路由 注意 由于需要拿到编辑数据的标识 所以需要动态路由
- 添加动态路由
{ path: "/edit/:id", component: Edit }
- 编辑按钮添加跳转的属性
<router-link :to="{path:'/edit/'+item.id }">编辑</router-link>
- 编辑页面
<template>
<div>
<h2 class="sub-header">编辑</h2>
<form>
<div class="form-group">
<label for="exampleInputEmail1">姓名</label>
<input
type="text"
class="form-control"
v-model="formData.name"
placeholder="请输入姓名"
/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">性别</label>
<input
type="text"
class="form-control"
v-model="formData.gender"
placeholder="请输入性别"
/>
</div>
<button type="submit" class="btn btn-success">
更新
</button>
</form>
</div>
</template>
- 通过 id 获取数据
showInit() {
axios
.get("http://localhost:3000/heroes/" + this.$route.params.id)
.then((rep) => {
this.formData = rep.data;
});
},
页面加载完成时,执行该方法将数据回显到页面
mounted() {
this.showInit();
},
- 新增编辑事件
<button type="submit" @click="updateI" class="btn btn-success">
更新
</button>
updateI() {
if (this.formData.name && this.formData.gender) {
axios
.put("http://localhost:3000/heroes/" + this.$route.params.id, {
name: this.formData.name,
gender: this.formData.gender,
})
.then((rep) => {
if (rep.status == 200) {
this.$router.push({
path: "/",
});
} else {
alert("修改失败");
}
});
} else {
alert("不能为空");
}
},
注意:
- 需要判断输入框是否为空
- axios 发送更新请求需要传回 id、数据
- 请求完成后,使用编程式导航,跳转到列表页面
案例优化:axios 统一导入
每次组件使用到 axios 时,都需要导入 axios ,配置 axios 后不需要再导入
步骤:
- 在入口 main.js 文件中引入 axios,并赋值给全局 Vue 对象的原型
import Axios from "axios";
Vue.prototype.$http = Axios
- 调用接口时 采用 实例.属性的方式即可调用
this.$http
案例优化:设置 baseUrl
步骤 :
- 给 axios 中的 baseUrl 设置常态值
Axios.defaults.baseURL = "http://localhost:3000"; // 设置共享的方法
- 使用
// 没改造之前
'http://localhost:3000/heroes/'
// 设置完常态值
'/heroes/'
案例优化:统一设置激活样式
点击左边侧边栏时,路由跳转时,不知道点击的是哪一个,使用激活样式,显示点击的栏
router.js 的路由表上面加上
linkActiveClass: "active", // active为bootstrap中的 一个class样式