开发规范
新增 view
在@/views文件下 创建对应的文件夹,一般性一个路由对应一个文件, 该模块下的功能就建议在本文件夹下创建一个新文件夹,各个功能模块维护自己的utils或components组件。
新增 api
在 @/api文件夹下创建本模块对应的 api 服务。
新增组件
在全局的 @/components写一些全局的组件,如富文本,各种搜索组件,封装的分页组件等等能被公用的组件。 每个页面或者模块特定的业务组件则会写在当前 @/views下面。 如:@/views/articlenews/components/xxx.vue。这样拆分大大减轻了维护成本。
请记住拆分组件最大的好处不是公用而是可维护性!
组件名
在注册一个组件的时候,我们始终需要给它一个名字。比如在全局注册的时候我们已经看到了
Vue.component('my-component-name', { /* ... */ })
定义组件名的方式有两种:
使用 kebab-case
Vue.component('my-component-name', { /* ... */ })
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如<my-component-name>
。
使用 PascalCase
Vue.component('MyComponentName', { /* ... */ })
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说<my-component-name>
和 <MyComponentName>
都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的
全局注册
在@/main.js文件下注册组件。
import countTo from 'vue-count-to'
Vue.component('countTo', countTo)
<template>
<count-to :startVal='startVal' :endVal='endVal' :duration='3000'></count-to>
</template>
局部注册
在对应页使用components注册组件。
<template>
<div class="app-container">
<el-card>
<article-detail />
</el-card>
</div>
</template>
<script>
import ArticleDetail from './components/ArticleDetail.vue'
export default {
name: 'CreateArticle',
components: {
ArticleDetail
},
}
</script>
新增样式
页面的样式和组件是一个道理,全局的 @/style (opens new window)放置一下全局公用的样式,每一个页面的样式就写在当前 views下面,请记住加上scoped 就只会作用在当前组件内了,避免造成全局的样式污染。
<style>
/* global styles */
</style>
<style scoped>
/* local styles */
.xxx-container{
/* name scoped */
xxx
}
</style>
请求流程
交互流程
一个完整的前端 UI 交互到服务端处理流程是这样的:
UI 组件交互操作;
调用统一管理的 api service 请求函数;
使用封装的 request.js 发送请求;
获取服务端返回;
更新 data;
为了方便管理维护,统一的请求处理都放在 @/src/api 文件夹中,并且一般按照 model 纬度进行拆分文件,如:
api/
system/
user.js
role.js
monitor/
operlog.js
logininfor.js
...
提示
其中,@/src/utils/request.js是基于 axios 的封装,便于统一处理 POST,GET 等请求参数,请求头,以及错误提示信息等。 它封装了全局 request拦截器、response拦截器、统一的错误处理、统一做了超时处理、baseURL设置等。
请求示例
import http from '@/utils/request'
import defaultSettings from '@/settings'
/**
* 分页查询
* @param {查询条件} data
*/
export function GetAllCategoryTreeTable(data) {
return http.request({
url: 'Articlecategory/GetAllCategoryTreeTable',
method: 'get',
params: data,
baseURL: defaultSettings.apiCMSUrl // 直接通过覆盖的方式
})
}/**
* 获取所有可用的
*/
export function getAllArticlecategoryList() {
return http.request({
url: 'Articlecategory/GetAllEnable',
method: 'get',
baseURL: defaultSettings.apiCMSUrl // 直接通过覆盖的方式
})
}
页面调用
import { GetAllCategoryTreeTable, getArticlecategoryDetail,
saveArticlecategory, setArticlecategoryEnable, deleteSoftArticlecategory,
deleteArticlecategory } from '@/api/cms/articlecategory'
import elDragDialog from '@/directive/el-drag-dialog' // base on element-ui
export default {
name: 'Articlecategory',
directives: { elDragDialog },
data() {
return {
searchform: {
keywords: ''
},
loadBtnFunc: [],
tableData: [],
tableloading: true,
pagination: {
currentPage: 1,
pagesize: 20,
pageTotal: 0
},
sortableData: {
order: 'desc',
sort: 'CreatorTime'
},
dialogEditFormVisible: false,
editFormTitle: '',
editFrom: {},
rules: {
Title: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
]
},
formLabelWidth: '120px',
currentId: '', // 当前操作对象的ID值,主要用于修改
currentSelected: [],
selectedCategoryOptions: '',
selectCategory: []
}
},
created() {
this.pagination.currentPage = 1
this.InitDictItem()
this.loadTableData()
this.loadBtnFunc = JSON.parse(localStorage.getItem('yueboncurrentfuns'))
},
methods: {
/**
* 初始化数据
*/
InitDictItem() {
},
/**
* 加载页面table数据
*/
loadTableData: function() {
this.tableloading = true
var seachdata = {
keyword: this.searchform.keywords
}
GetAllCategoryTreeTable(seachdata).then(res => {
this.tableData = res.ResData
this.selectCategory = res.ResData
this.tableloading = false
})
},
/**
* 点击查询
*/
handleSearch: function() {
this.pagination.currentPage = 1
this.loadTableData()
},
}
}
引入依赖
除了 element-ui 组件以及脚手架内置的业务组件,有时我们还需要引入其他外部组件,这里以引入 vue-count-to (opens new window)为例进行介绍。
在终端输入下面的命令完成安装:
$ npm install vue-count-to --save
加上--save
参数会自动添加依赖到package.json
中去。
权限使用
封装了一个指令权限,能简单快速的实现按钮级别的权限判断。v-permission
<!-- 存在权限字符串才能看到-->
<el-button v-hasPermi="['Menu/Add']" type="primary" icon="el-icon-plus" size="mini" @click="ShowMenuEditOrViewDialog()">新增</el-button>
页签缓存
由于目前 keep-alive 和 router-view 是强耦合的,而且查看文档和源码不难发现 keep-alive 的 include (opens new window)默认是优先匹配组件的 name ,所以在编写路由 router 和路由对应的 view component 的时候一定要确保 两者的 name 是完全一致的。(切记 name 命名时候尽量保证唯一性 切记不要和某些组件的命名重复了,不然会递归引用最后内存溢出等问题)
//router 路由声明
{
path: 'LogLogin',
component: ()=>import('@/views/syslog/login'),
name: 'LogLogin',
meta: { title: '登录日志', icon: 'log' }
}
//路由对应的view /syslog/login
export default {
name: 'LogLogin'
}
一定要保证两着的名字相同,切记写重或者写错。默认如果不写 name 就不会被缓存
提示
在系统管理-菜单管理-可以配置菜单页签是否缓存,默认为缓存
使用图标
全局Svg Icon
图标组件。
默认在 @/icons/index.js中注册到全局中,可以在项目中任意地方使用。所以图标均可在 @/icons/svg。可自行添加或者删除图标,所以图标都会被自动导入,无需手动操作。
使用方式
<!-- icon-class 为 icon 的名字; class-name 为 icon 自定义 class-->
<svg-icon icon-class="password" class-name='custom-class' />
改变颜色
svg-icon 默认会读取其父级的 color fill: currentColor;
你可以改变父级的color或者直接改变fill的颜色即可。
提示
如果你是从 iconfont (opens new window)下载的图标,记得使用如 Sketch 等工具规范一下图标的大小问题,不然可能会造成项目中的图标大小尺寸不统一的问题。 本项目中使用的图标都是 128*128 大小规格的。
如遇到问题到Issues反馈