赞
踩
再梳理一遍
Authorization
字段提供token
令牌(axios拦截器)baseUrl
,接口地址:http://localhost:8888/api/private/v1/token令牌在服务端生成,当登录成功时,post请求返回的用户信息里包含了这一元素:
Axios:通过promise实现对ajax技术的一种封装,ajax只能访问同源的请求。axios并没有install 方法,所以是不能使用vue.use()方法的。为了不在每个文件都引用一次axios,将它改造成vue插件。
1)使用
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
2) 改造为vue插件
plugins/http.js
import axios from 'axios'
const httpHelper = {}
// 配置Vue插件
httpHelper.install = function fn (Vue) {
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1'
Vue.prototype.$http = axios
}
export default httpHelper
main.js里安装插件
import http from '@/plugins/http.js'
Vue.use(http)
httpAxios.install = function (Vue) { const instance = axios.create({ baseURL: 'http://127.0.0.1:8888/api/private/v1' }) instance.interceptors.request.use(function (config) { if (config.url.toLowerCase() !== 'login') { const token = sessionStorage.getItem('token') config.headers.Authorization = token } return config }, function (error) { return Promise.reject(error) }) Vue.prototype.$http = instance }
路由的前置守卫 router.js
router.beforeEach((to, from, next) => {
console.log(to, from)
if (to.name === 'login') {
next()
} else {
const token = sessionStorage.getItem('token')
if (!token) {
router.push({ 'name': 'login' })
Message.warning('请先登录')
return
}
next()
}
})
handleLogin () {
this.$http.post('login', this.formData)
.then((res) => {
const data = res.data
const {meta: {status, msg}} = data
if (status === 200) {
const token = data.data.token
sessionStorage.setItem('token', token)
this.$message.success(msg)
} else {
this.$message.error(msg)
}
})
}
async handleLogin () {
const res = await this.$http.post('login', this.formData)
const data = res.data
const { meta: { status, msg } } = data
if (status === 200) {
const token = data.data.token
sessionStorage.setItem('token', token)
this.$message.success(msg)
} else {
this.$message.error(msg)
}
}
外层方法使用async
关键字(await最近的外层函数要加上async),发请求代码前加 await
,省略.then
以自定义面包屑组件(子组件)为例,父组件(使用到面包屑的组件)向子组件传值。
子组件:
<template>
<!-- 面包屑 -->
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>{{this.level1}}</el-breadcrumb-item>
<el-breadcrumb-item>{{this.level2}}</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script>
export default {
name: 'my-bread',
props: ['level1', 'level2']
}
</script>
父组件:
<my-bread level1='权限管理' level2='角色列表'></my-bread>
show-password
sessionStorage.clear()
this.$router.push({name: 'login'})
一级菜单和子菜单之间是并列关系,在知道有几级菜单的情况下,思考:如果不知道有几级菜单?
<el-menu :unique-opened=true :router=true>
<el-submenu :index="item1.order.toString()" v-for="(item1,i) in menus" :key="item1.id">
<template slot="title">
<i :class="iconlist[i]"></i>
<span>{{item1.authName}}</span>
</template>
<el-menu-item :index="item2.path" v-for="item2 in item1.children" :key="item2.id">
<i class="el-icon-menu"></i>
<span>{{item2.authName}}</span>
</el-menu-item>
</el-submenu>
</el-menu>
GET
POST
PUT
DELETE
显示:
在created的时候,调用this.getUserList()
,拿到res的数据,赋值给data里的userlist
const res = await this.$http.get(`users?query=${this.query}&pagenum=${this.pagenum}&pagesize=${this.pagesize}`)
搜索:
<el-input @clear="getUserList" v-model="query" clearable @keyup.enter.native="getUserList">
键盘抬起时/输入框清空时,依然是触发getUserList
,该方法内部通过双向数据绑定的query
进行传参查询,接口文档中,query
参数可以为空,为空时显示全量信息。
<el-table-column label="用户状态">
<template slot-scope="scope">
<!-- scope.row就是当前绑定的数据对象 -->
<el-switch @change="handleSwitchChange(scope.row)" v-model="scope.row.mg_state" active-color="#13ce66"
inactive-color="#ff4949">
</el-switch>
</template>
</el-table-column>
for (const key in this.formData) {
this.formData[key] = ''
}
编辑按钮所在行,通过slot-scope="scope"
将被编辑用户信息传给方法editUser
,通过初始化form(显示用户信息的el-form所绑定的内容)展示
editUser(user) {
this.dialogFormVisibleEdit = true
this.form = user
}
<el-dialog title="编辑用户" :visible.sync="dialogFormVisibleEdit">
<el-form :model="form">
<el-form-item label="用户名" >
<el-input v-model="form.username" disabled></el-input>
</el-form-item>
</el-form>
</el-dialog>
selected
属性的option,会默认选中一到三级权限的名词展示,可以作为后台的文档数据,不必作为一项功能
请求角色列表的产物,因此数据包含在getRoleList
的返回值里。
理解el-row和el-col的关系,两者包含成为一维。
<el-row :gutter="20">
<el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
</el-row>
{ "data": [ { "id": 30, "roleName": "主管", "roleDesc": "技术负责人", "children": [ { "id": 101, "authName": "商品管理", "path": null, "children": [ { "id": 104, "authName": "商品列表", "path": null, "children": [ { "id": 105, "authName": "添加商品", "path": null } ] } ] } ] } ], }
代码怎么写:
<el-row v-for="(item1,i) in scope.row.children" :key="i" class="expand"> <!-- 第一列中放一级标签 --> <el-col :span="4"> <!-- 可移除标签,这里展示一级标签,绑定取消权限方法 --> <el-tag class="expand" closable @close="delRight(item1.id,scope.row)">{{item1.authName}}</el-tag> </el-col> <el-col :span="20"> <!-- 第二列也是一行两列 --> <el-row v-for="(item2,index) in item1.children" :key="index"> <!-- 第二行第一列中放二级标签 --> <el-col :span="4"> <el-tag class="expand" type="success" closable @close="delRight(item2.id,scope.row)">{{item2.authName}} </el-tag> </el-col> <el-col :span="20"> <el-tag class="expand" @close="delRight(item3.id,scope.row)" closable type="warning" v-for="(item3,indexInner) in item2.children" :key="indexInner">{{item3.authName}}</el-tag> </el-col> </el-row> </el-col> </el-row>
default-expand-all
)checklistArr
):default-checked-keys="checklistArr"
显示:
editRight(role) { // checklist权限的集合,是个树形结构 this.checklist = role.children this.currentRoleId = role.id var tmpArr = [] this.checklist.forEach(item1 => { var item2 = item1.children item2.forEach(item2 => { var item3 = item2.children item3.forEach(item3 => { tmpArr.push(item3.id) }) }) }) this.checklistArr = tmpArr }
提交:
async confirmRole() {
let arr1 = this.$refs.mytree.getCheckedKeys()
let arr2 = this.$refs.mytree.getHalfCheckedKeys()
let arr = [...arr1, ...arr2]
const res = await this.$http.post(`roles/${this.currentRoleId}/rights`, { rids: arr.join(',') })
}
分类接口设计:
重要参数type
,type=2(返回一层、二层分类),type=3(返回前三层分类)
<el-tree-grid
treeKey="cat_id"
parentKey="cat_pid"
levelKey="cat_level"
childKey="children"
prop="cat_name"
label="分类名称">
</el-tree-grid>
handleChange
方法,能获取到最接近一层的父类参数分类id,配置级别和分类名称,组成一个obj作为参数发POST请求 handleChange(value) {
console.log(value);
}
如何限定只让第三级被选中:
handleChange () {
if (this.selectedOptions.length !== 3) {
this.$message.warning('商品只能添加到三级分类')
this.selectedOptions.length = 0
}
}
在el-tab-pane
里含了el-table
–绑定dynamicAttrs el-button
在点击了级联选择器器之后,渲染出动、静态参数
async handleChange() { if (this.value.length === 3) { if (this.active === '1') { // 动态参数 const res = await this.$http.get(`categories/${this.value[2]}/attributes?sel=many`) this.dynamicAttrs = res.data.data this.dynamicAttrs.forEach((item) => { // 把attr_vals转为数组类型 item.attr_vals = item.attr_vals.split(',') }) } else if (this.active === '2') { const res1 = await this.$http.get(`categories/${this.value[2]}/attributes?sel=only`) this.staticAttrs = res1.data.data } } }
商品参数数据格式:
参数名–参数值(可能有多个)
"data": [
{
"attr_id": 1,
"attr_name": "cpu",
"cat_id": 22,
"attr_sel": "only",
"attr_write": "manual",
"attr_vals": "2G","4G","8G"
}
],
改了表字段的数据类型,可能不是最合适,但是时间显示正常了。创建时间的时候,还是以1970位默认值。
请求上传接口,需要设置token(这里不是发axios请求)
<el-upload
action="http://47.xxx.1xx.7:8888/api/private/v1/upload"
:headers="header"
:on-remove="handleRemove"
:on-success="handleSuccess"
:file-list="fileList"
list-type="picture">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
header: {
Authorization: sessionStorage.getItem('token')
}
<quill-editor v-model="form.goods_introduce"></quill-editor>
JSX
,学习成本),vue(模板):任何合乎规范的 HTML 都是合法的 Vue 模板。可以在单文件组件里完全控制 CSS,将其作为组件代码的一部分。vue create mypro
cd mypro
vue add element
这里选择的是按需引入:
观察项目文件夹中多了plugins-element.js
默认按需引入只引入了{Button组件} (可以减小体积),修改代码
一般脚手架都应当有以下的几个功能:
定义好项目的目录结构
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。