0 前后端分离开发
0.1 接口文档管理平台:Yapi
Yapi的两个主要功能:
- API接口管理
- Mock服务(生成接口的模拟测试数据)
使用:
- 添加项目
- 添加分类
- 添加接口
示例:
- mock地址:https://yapi.pro/mock/376827/user/getById
- 数据:
1 前端工程化:
指在企业级的前端项目开发中,把前端开发所需的工具、技术、流程、经验等进行规范化、标准化。
- 模块化:JS、CSS
- 组件化:UI结构、样式、行为
- 规范化:目录结构、编码、接口
- 自动化:构建、部署、测试
1.1 环境准备(Vue-cli):
- 介绍:Vue-cli是Vue官方提供的一个脚手架,用于快速生成一个Vue项目模板。
- 功能:
- 统一的目录结构
- 本地测试
- 热部署
- 单元测试
- 集成打包上线
- 依赖环境:Node.js
具体步骤直接参考:Day03-04. 前端工程化-环境准备_哔哩哔哩_bilibili
此处npm下载镜像站:npmmirror 镜像站
1.2 Vue项目简介:
创建:
在目标文件夹内打开cmd,输入:
- 命令行:
vue create vue-project01
- 图形化界面:
vue ui
创建过程详情参考:Day03-05. 前端工程化-Vue项目_哔哩哔哩_bilibili
Vue项目-目录结构:
Vue项目-运行:
Vue项目-配置端口(默认8080):
在vue.config.js文件中修改:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
// 配置端口
devServer:{
port:7000,
}
})
1.3 Vue项目开发流程:
开发项目:
- 在开发项目过程中,您主要会编辑src目录中的Vue文件(.vue文件),这些文件包含了项目的组件、路由、样式等内容。
- 您还需编辑src目录中的App.vue文件,这是项目的根组件。
- 修改src目录中的main.js文件来初始化Vue应用程序。
- 如果需要引入外部库或插件,可以在src目录中的main.js文件中进行配置。
- 默认首页:index.html
- 默认首页index默认引入 入口文件: main.js ,如下:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
- 此处 import 代表引入模块
- 对应 export 将对象或函数导出为模块
下面创建Vue对象相当于之前的:
new Vue({
el:'#app',//index中的id=app
router:router,//路由
render:h=>h(App)// 将上面导入的app视图创建出对应的虚拟DOM元素,挂载到上面的#app
})
- Vue的组件文件以 .vue 结尾,每个组件由三个部分组成:
- <template>:模板部分:定义HTML代码.一个<template>必须有且只能有一个div
- <script>:主要控制模板中的数据来源和行为
- <style>:CSS样式
示例:
App.vue:
此处data中function是一个匿名函数,可以简写如下:
<template>
<!-- 在一个.vue文件中只能有一个Vue实例对象,通常不需要为<template>中的<div>绑定ID -->
<div>
{{message}}
</div>
</template>
<script>
export default {
//这里的data与之前的data:XXX 数据模型不一样,export出去的是函数,所以这样写:
data:function() {
return {
message:"Hello Vue!"
}
},
/*
也可简写为:
data() {
return {
message:"Hello Vue!"
}
},
*/
methods: {
}
}
</script>
<style>
</style>
进行Vue工程开发,很少去操作 index.html 与 main.js ,主要操作组件,即.vue文件
2 Vue组件库Element
2.0 介绍:
- Element:是饿了么团队研发的,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库;
- 组件:组成网页的部件,例如 超链接、按钮、图片、表格、表单、分页条等等。
2.1 快速入门
- 安装ElementUI组件库(在当前工程的目录下),在命令行执行指令:
npm install element-ui@2.51.3
- 在main.js中引入Element组件库
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
- 定义组件文件,访问官网,复制组件代码,调整
这里将其他组件放在views/element 下
ElementView.vue:
<template>
<el-row>
<el-button round>圆角按钮</el-button>
<el-button type="primary" round>主要按钮</el-button>
<el-button type="success" round>成功按钮</el-button>
<el-button type="info" round>信息按钮</el-button>
<el-button type="warning" round>警告按钮</el-button>
<el-button type="danger" round>危险按钮</el-button>
</el-row>
</template>
<script>
export default {
}
</script>
<style>
</style>
修改后的App.vue:
重要:
- components 的作用是将名为
ElementView
的组件注册为当前组件的子组件。 - <element-view></element-view>组件是当你引入ElementView这个自定义组件并在components中注册后,Vue自动生成的标签,至于中间的 – ,是因为HTML并不分大小写,Vue自己将<ElementView>转换为<element-view>。如果是Component1组件,就通过<component1></component1>使用组件。
<template>
<div>
<!-- 在根组件当中引用其他组件: -->
<element-view></element-view>
</div>
</template>
<script>
import ElementView from './views/element/ElementView.vue'
export default {
//子组件必须在 components : 中注册
components: { ElementView },
data:function() {
return {
message:"Hello Vue!"
}
},
methods: {
}
}
</script>
<style>
</style>
2.2.1 常用组件-Table表格:
具体操作同上,注意<template> 与<script>内的内容都要复制。
ElementView.vue:
<template>
<div>
<el-row>
<!-- button 按钮 -->
<el-button round>圆角按钮</el-button>
<el-button type="primary" round>主要按钮</el-button>
<el-button type="success" round>成功按钮</el-button>
<el-button type="info" round>信息按钮</el-button>
<el-button type="warning" round>警告按钮</el-button>
<el-button type="danger" round>危险按钮</el-button>
</el-row>
<br />
<!-- table 表格 -->
<el-table :data="tableData" border="true" style="width: 100%">
<el-table-column prop="date" label="日期" width="180"> </el-table-column>
<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</el-table>
<br />
</div>
</template>
<script>
export default {
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄",
},
{
date: "2016-05-04",
name: "王小虎",
address: "上海市普陀区金沙江路 1517 弄",
},
{
date: "2016-05-01",
name: "王小虎",
address: "上海市普陀区金沙江路 1519 弄",
},
{
date: "2016-05-03",
name: "王小虎",
address: "上海市普陀区金沙江路 1516 弄",
},
],
};
},
methods: {
}
};
</script>
<style>
</style>
2.2.2 常用组件-Pagination 分页:
本小结引入了vue组件事件的概念,事件的函数使用了一个新概念:回调参数
如:
methods: {
handleSizeChange(val){
alert(val);
},
handleCurrentChange(val){
alert(val);
}
}
methods中的这两个val。
在此处我简单理解为当 在<el-Paginatiion> 中使用事件@size-change=”handleSizeChange”指定函数为handleSizeChange时,Vue变自动的为handleSizeChange()添加了一个参数(参数内容详见Element中该组件的官方文档),而在methods中想使用这个参数,任意的在参数表内写一个变量接收变可以使用这个参数。
<template>
<div>
<el-row>
<!-- button 按钮 -->
<el-button round>圆角按钮</el-button>
<el-button type="primary" round>主要按钮</el-button>
<el-button type="success" round>成功按钮</el-button>
<el-button type="info" round>信息按钮</el-button>
<el-button type="warning" round>警告按钮</el-button>
<el-button type="danger" round>危险按钮</el-button>
</el-row>
<br />
<!-- table 表格 -->
<el-table :data="tableData" border="true" style="width: 100%">
<el-table-column prop="date" label="日期" width="180"> </el-table-column>
<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</el-table>
<br />
<!-- pagunation 分页 -->
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" background layout="prev, pager, next,jumper" :total="1000" ></el-pagination>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄",
},
{
date: "2016-05-04",
name: "王小虎",
address: "上海市普陀区金沙江路 1517 弄",
},
{
date: "2016-05-01",
name: "王小虎",
address: "上海市普陀区金沙江路 1519 弄",
},
{
date: "2016-05-03",
name: "王小虎",
address: "上海市普陀区金沙江路 1516 弄",
},
],
};
},
methods: {
handleSizeChange(val){
alert(val);
},
handleCurrentChange(val){
alert(val);
}
}
};
</script>
<style>
</style>
2.2.3 常用组件-Dialog 对话框:
在保留当前页面信息的情况下,告知用户并承载相关操作。
<template>
<div>
<el-button type="text" @click="dialogTableVisible = true">打开嵌套表格的 Dialog</el-button>
<el-dialog title="收货地址" :visible.sync="dialogTableVisible">
<el-table :data="gridData">
<el-table-column property="date" label="日期" width="150"></el-table-column>
<el-table-column property="name" label="姓名" width="200"></el-table-column>
<el-table-column property="address" label="地址"></el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
gridData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}],
dialogTableVisible: false
};
},
methods: {
}
};
</script>
<style>
</style>
此处Vue帮你做的事有很多,感觉有点过于智能了,比如:
当你关闭对话框后,
dialogTableVisible
将会变成false
。这是因为在模板中,对话框的可见性是通过:visible.sync="dialogTableVisible"
进行控制的,.sync
修饰符确保了dialogTableVisible
的变化会同步更新到对话框的可见性。虽然确实没有直接看到对dialogTableVisible
的值进行修改的代码,但是在 Vue.js 中,<el-dialog>
组件的:visible.sync
属性会创建一个名为update:visible
的事件监听器,以便在对话框的可见性发生变化时更新dialogTableVisible
的值。简而言之,dialogTableVisible
的值会在对话框的可见性发生变化时自动更新。所以,当你关闭对话框时,Vue.js 会自动将dialogTableVisible
的值设置为false
。
2.2.4 常用组件-Form 表单:
由输入框、选择器、点选框、多选框、等控件构成,用以收集、校验、提交数据。
<template>
<div>
<el-button type="text" @click="dialogFormVisible = true"
>打开Form表单的Dialog</el-button
>
<el-dialog title="活动申请表单" :visible.sync="dialogFormVisible">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="活动名称">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="活动区域">
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间">
<el-col :span="11">
<el-date-picker
type="date"
placeholder="选择日期"
v-model="form.date1"
style="width: 100%"
></el-date-picker>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-time-picker
placeholder="选择时间"
v-model="form.date2"
style="width: 100%"
></el-time-picker>
</el-col>
</el-form-item>
<el-form-item label="即时配送">
<el-switch v-model="form.delivery"></el-switch>
</el-form-item>
<el-form-item label="活动性质">
<el-checkbox-group v-model="form.type">
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="特殊资源">
<el-radio-group v-model="form.resource">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活动形式">
<el-input type="textarea" v-model="form.desc"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
dialogFormVisible: false,
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
}
};
},
methods: {
onSubmit() {
alert(JSON.stringify(this.form));
}
}
};
</script>
<style>
</style>
2.3 综合案例:
实现员工管理页面开发,并通过Axois实现异步数据加载。
1 创建EmpView.vue组件,并在App.vue根组件中引入:
App.vue:
<template>
<emp-view></emp-view>
</template>
<script>
import EmpView from './views/EmpView.vue';
export default {
components: { EmpView },
data: function () {
return {
};
},
methods: {},
};
</script>
<style>
</style>
2 实现基本页面布局:
使用Container 布局容器。
3 实现各个组件:
EmpView.vue:
<template>
<el-container style="height: 500px; border: 1px solid #eee">
<el-header>Element管理系统</el-header>
<el-container>
<el-aside width="200px">
<el-menu>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-message"></i>系统信息管理</template
>
<el-menu-item-group>
<el-menu-item index="1-1">部门管理</el-menu-item>
<el-menu-item index="1-2">员工管理</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-main>
<!-- 表单 -->
<el-form :inline="true" :model="searchForm" class="demo-form-inline">
<el-form-item label="姓名">
<el-input v-model="searchForm.name" placeholder="姓名"></el-input>
</el-form-item>
<el-form-item label="性别">
<el-select v-model="searchForm.gender" placeholder="性别">
<el-option label="男" value="1"></el-option>
<el-option label="女" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="日期">
<el-date-picker
v-model="searchForm.entrydate"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
<!-- 表格 -->
<el-table :data="tableData" border="">
<el-table-column
prop="name"
label="姓名"
width="180"
></el-table-column>
<el-table-column
prop="image"
label="图像"
width="180"
></el-table-column>
<el-table-column
prop="gender"
label="性别"
width="140"
></el-table-column>
<el-table-column
prop="job"
label="职位"
width="140"
></el-table-column>
<el-table-column
prop="entrydate"
label="入职日期"
width="180"
></el-table-column>
<el-table-column
prop="updatetime"
label="最后操作时间"
width="230"
></el-table-column>
<el-table-column label="操作">
<el-button type="primary" size="mini">编辑</el-button>
<el-button type="danger" size="mini">删除</el-button>
</el-table-column>
</el-table>
<!-- 分页条 -->
<center>
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" background layout="prev, pager, next,jumper" :total="1000" ></el-pagination>
</center>
</el-main>
</el-container>
</el-container>
<el-footer>Footer</el-footer>
</el-container>
</template>
<script>
export default {
data() {
return {
tableData: [],
searchForm: {
name: " ",
gender: "",
entrydate:[],
},
};
},
methods: {
onSubmit: function () {
alert("查询数据!");
},
handleSizeChange(val){
alert(val);
},
handleCurrentChange(val){
alert(val);
},
},
};
</script>
<style>
.el-header {
background-color: #b3c0d1;
color: #333;
text-align: center;
font-size: 40px;
line-height: 60px;
}
.el-footer {
background-color: #b3c0d1;
color: #333;
text-align: center;
font-size: 10px;
line-height: 60px;
}
.el-aside {
background-color: #d3dce6;
color: #333;
text-align: center;
line-height: 200px;
}
/* .el-main {
background-color: #e9eef3;
color: #333;
text-align: center;
line-height: 160px;
} */
</style>
4 列表项目的异步加载,并渲染展示:
mock:https://mock.apifox.cn/m1/3128855-0-default/emp/list
注意这里图像和性别在表格中的处理方式:
<template slot-scope="scope">的使用
EmpView.vue:
<template>
<el-container style="height: 500px; border: 1px solid #eee">
<el-header>Element管理系统</el-header>
<el-container>
<el-aside width="200px">
<el-menu>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-message"></i>系统信息管理</template
>
<el-menu-item-group>
<el-menu-item index="1-1">部门管理</el-menu-item>
<el-menu-item index="1-2">员工管理</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-main>
<!-- 表单 -->
<el-form :inline="true" :model="searchForm" class="demo-form-inline">
<el-form-item label="姓名">
<el-input
v-model="searchForm.name"
placeholder="姓名"
></el-input> </el-form-item
>
<el-form-item label="性别">
<el-select v-model="searchForm.gender" placeholder="性别">
<el-option label="男" value="1"></el-option>
<el-option label="女" value="2"></el-option>
</el-select> </el-form-item
>
<el-form-item label="日期">
<el-date-picker
v-model="searchForm.entrydate"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker> </el-form-item
>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
<!-- 表格 -->
<el-table :data="tableData" border="">
<el-table-column
prop="name"
label="姓名"
width="180"
></el-table-column>
<el-table-column
label="图像"
width="180"
>
<template slot-scope="scope">
<img :src="scope.row.image" height="100px">
</template>
</el-table-column>
<!-- <el-table-column
prop="gender"
label="性别"
width="140"
></el-table-column> -->
<!-- <el-table-column
v-if="tableData.gender==1"
prop="gender"
label="性别"
width="140"
>男</el-table-column>
<el-table-column
v-else-if="tableData.gender==2"
prop="gender"
label="性别"
width="140"
>女</el-table-column> -->
<el-table-column prop="gender" label="性别" width="140">
<template slot-scope="scope">
{{ scope.row.gender === 1 ? "男" : "女" }}
</template>
</el-table-column>
<el-table-column
prop="job"
label="职位"
width="140"
></el-table-column>
<el-table-column
prop="entrydate"
label="入职日期"
width="180"
></el-table-column>
<el-table-column
prop="updatetime"
label="最后操作时间"
width="230"
></el-table-column>
<el-table-column label="操作">
<el-button type="primary" size="mini">编辑</el-button>
<el-button type="danger" size="mini">删除</el-button>
</el-table-column>
</el-table>
<!-- 分页条 -->
<center>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
background
layout="prev, pager, next,jumper"
:total="1000"
></el-pagination>
</center>
</el-main>
</el-container>
</el-container>
<el-footer>Footer</el-footer>
</el-container>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
tableData: [],
searchForm: {
name: " ",
gender: "",
entrydate: [],
},
};
},
methods: {
onSubmit: function () {
alert("查询数据!");
},
handleSizeChange(val) {
alert(val);
},
handleCurrentChange(val) {
alert(val);
},
},
mounted() {
//发送
axios
.get("https://mock.apifox.cn/m1/3128855-0-default/emp/list")
.then((result) => {
this.tableData = result.data.data;
});
},
};
</script>
<style>
.el-header {
background-color: #b3c0d1;
color: #333;
text-align: center;
font-size: 40px;
line-height: 60px;
}
.el-footer {
background-color: #b3c0d1;
color: #333;
text-align: center;
font-size: 10px;
line-height: 60px;
}
.el-aside {
background-color: #d3dce6;
color: #333;
text-align: center;
line-height: 200px;
}
/* .el-main {
background-color: #e9eef3;
color: #333;
text-align: center;
line-height: 160px;
} */
</style>
最终效果如下: