本博文记录了在vue项目开发中的一些经验,具体包含:class动态绑定、子页面刷新、注入函数到子页面、数据加载效果、单击后编辑、文件上传、数据分页、表单提交等的使用记录。
1、class动态绑定
根据变量的值绑定不同的class样式,这里ftype的值可为full_label、zero_label、has_label三种class样式名
html
<div class="folderImg" :class="ftype" @click="to_url('showimglist',fd.name)">
<i class="el-icon-folder-opened avatar-uploader-icon"></i>
</div>
对应的class设置有
css
.full_label {
background-image: url(../../assets/full_label.png);
background-repeat:no-repeat;
background-size:100% 100%;
-moz-background-size:100% 100%;
}
.zero_label {
background-image: url(../../assets/zero_label.png);
background-repeat:no-repeat;
background-size:100% 100%;
-moz-background-size:100% 100%;
}
.has_label {
background-image: url(../../assets/has_label.png);
background-repeat:no-repeat;
background-size:100% 100%;
-moz-background-size:100% 100%;
}
2、子页面刷新 | 注入函数到子页面
通过v-if的方式设置子页面不可见,然后在this.$nextTick设置子页面可见,从而实现对子页面的刷新。然后将封装为reload函数,并注入函数到子页面,在子页面调用即可。
具体参考:https://www.jb51.net/article/260561.htm
html
<template>
<div id="app">
<!--img src="./assets/logo.png"-->
<router-view v-if="isRouterAlive"></router-view>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'App',
provide () { //设置被注入到子页面的函数
return {
reload: this.reload,
}
},
data () {
return {
isRouterAlive: true,
}
},
methods: {
reload () {
this.isRouterAlive = false
this.$nextTick(function () {
this.isRouterAlive = true
})
},
}
}
</script>
子页面的js中设置inject即可在子页面刷新内容
html
//子页面
<script>
export default {
name: 'showanalysis',
inject: ['reload'], //接收父页面注入的内容
}
</script>
3、数据加载效果
用于服务器返回结果中的过程界面(当前端调用后台接口时触发该效果,获取到结果后取消显示)
具体参考 https://element.faas.ele.me/#/zh-CN/component/loading#loading-jia-zai
具体用例如下,在元素中添加v-loading属性绑定变量loading,默认为false不显示效果;当触发其他耗时操作时,修改loading为true,显示加载中效果;当操作完成时,修改loading为false。
html
<template>
<div class="demo-image"
v-loading="loading"
element-loading-text="等待服务器处理中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)"
>
</div>
</template>
<script>
export default {
name: 'showdatafolder',
data() {
return {
loading: false,
}
},
}
}
</script>
4、宽高百分比
使用vh,vw来控制元素相对于屏幕的宽高百分比。vh和wh是视口单位,是相对长度单位。wh是相对于视口的宽度,"1vw"等于视口宽度的"1%";而vh是相对于视口的高度,"1vh"等于视口高度的"1%"
具体参考:https://www.php.cn/faq/489349.html
5、单击后编辑
text类控件在单击后转换为input控件,在失去焦点后又变换text类空间。
以下为el-button控件与el-input控件的结合,当点击el-button后,与之对应的el-input展示,当el-input失去焦点后又显示为el-button。
html
<el-input
class="input-new-tag"
v-if="inputVisible"
v-model="inputValue"
ref="saveTagInput" #为控件取了一个名字
size="small"
@keyup.enter.native="handleInputConfirm"
@blur="handleInputConfirm"
>
</el-input>
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ New Tag</el-button>
<script>
export default {
data() {
return {
dynamicTags: ['标签一', '标签二', '标签三'],
inputVisible: false,
inputValue: ''
};
},
methods: {
showInput() {
this.inputVisible = true;
this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus();//设置指定控件获取输入焦点
});
},
handleInputConfirm() {
let inputValue = this.inputValue;
if (inputValue) {
this.dynamicTags.push(inputValue);
}
this.inputVisible = false;
this.inputValue = '';
}
}
}
</script>
关键解析:
1、通过v-if='inputVisible' , v-else
,绑定变量inputVisible设置el-button与与el-input的显示切换
2、为el-input控件设置ref,既为控件取名字。当点击button时,触发showInput事件
,设置el-input可见,并获取输入焦点
3、通过设置el-input的@blur与@keyup.enter.native
属性,对输入完成后的操作进行监听,并设置inputVisible = false
输入框不可见,inputValue = ''
输入框的值为空`
代码参考自:https://element.faas.ele.me/#/zh-CN/component/tag
单击前效果
控件输入时效果
6、文件上传
这里仅实现最简单的文件上传方式,多文件上传(实质为多次调用文件上传接口)请参考 https://element.faas.ele.me/#/zh-CN/component/upload
html页面
设置action为null,主要是在:before-upload
所绑定的函数中实现文件上传
html
<el-upload class="upload-demo" drag action="null" :before-upload="beforeAvatarUpload">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将pt文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传pt文件,且不超过500kb</div>
</el-upload>
js实现
在beforeAvatarUpload函数中,可以对文件后缀、文件size进行判断,最后使用axios创建post请求将文件提交到后端
js
beforeAvatarUpload(file) {
import axios from 'axios'
const isAllow = file.name.indexOf('.pt') > 0 || file.name.indexOf('.PT') > 0;
const isLt200M = file.size / 1024 / 1024 / 200;
if (!isAllow) {
this.$message.error("只允许上传pt文件!");
return false
} else if (!isLt200M) {
this.$message.error('上传模型大小不能超过 200MB!');
return false
} else {
//手动进行文件上传
let formData = new FormData();
formData.append("file", file);
axios({
url: "/api/uploader",//上传文件接口
method: "post",
headers: {
"Content-Type": "multipart/form-data",
},
data: formData,
}).then((res) => {
this.$message({
title: '结果提示',
message: res.data.msg,
type: 'success'
});
this.reload();
});
}
return false
},
后端代码
后端基于flask实现
python
@app.route('/uploader',methods=['GET','POST'])
def uploader():
if request.method == 'POST':
f = request.files['file']#跟表单里file中的name要一样
spath=os.path.join(runDir, f.filename)
print(spath)
f.save(spath)
json={'code':0,'msg':'文件上传成功!'}
return jsonify(json)
else:
return 'please uplaod file use post method!'
更多内容参考 https://element.faas.ele.me/#/zh-CN/component/upload
7、数据分页
在element-ui中详细介绍了分页控件的用法,但并未配合任何具体案例介绍。https://element.faas.ele.me/#/zh-CN/component/pagination
html页面
第一个部件为grid-content,里面v-for循环对应变量img_list,用于显示分页的具体内容
第二部分为el-pagination控件,对应具体的分页控件。可以通过修改layout对应的text,实现对分页部件内容的位置控制
html
<template>
<div class="demo-image"
>
<el-row>
<div class="grid-content">
<div class="block" v-for="d in img_list" :key="d">
<div class="demo-image__preview">
<el-image style="width: 200px; height: 200px" :src="d" :preview-src-list="img_list">
</el-image>
<div class="bottom clearfix">
<el-button type="text" class="button" @click="to_url('labelimg',{'currentImage':d})">标注</el-button>
<el-button type="text" class="button" @click="delete_img(d)">删除</el-button>
</div>
</div>
</div>
</div>
</el-row>
<el-row>
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="0"
:page-sizes="[6, 8, 10, 12, 15, 18]" :page-size="default_page_size"
layout="total, sizes, prev, pager, next, jumper" :total="all_img_list.length">
</el-pagination>
</el-row>
</div>
</template>
js实现
主要涉及的变量有all_img_list | 所有的数据、img_list | 当前分页的数据、default_page_size | 每一页的数据量、default_page | 当前页。
在页面初始化的时候,既mounted函数中获取全部数据设置到all_img_list中,并根据default_page_size、default_page截取当前页内容设置到img_list中。
html
<script>
import axios from 'axios'
export default {
name: 'showimglist',
data() {
return {
all_img_list: [],
img_list: [],
default_page_size: 10,
default_page: 1,
}
},
mounted() {
if(this.$route.query.dname){
localStorage.setItem('dname', this.$route.query.dname);
}
let dname = localStorage.getItem('dname');//this.$route.params.dname;
this.dname=dname;
if (dname) {
let formData = new FormData();
formData.append("dname", dname);
axios({
url: '/api/datamanage_get_imglist',//上传文件接口
method: "post",
headers: {
"Content-Type": "multipart/form-data",
},
data: formData,
}).then((res) => {
this.all_img_list = res.data;
this.img_list = this.all_img_list.slice(0, this.default_page_size)
});
}
},
methods: {
handleSizeChange(val) {
this.default_page_size = val;
this.img_list = this.all_img_list.slice((this.default_page - 1) * this.default_page_size, this.default_page * this.default_page_size);
},
handleCurrentChange(val) {
this.default_page = val
this.img_list = this.all_img_list.slice((this.default_page - 1) * this.default_page_size, this.default_page * this.default_page_size);
},
}
}
</script>
以上代码中,handleSizeChange用于监听分页数量的改变,handleCurrentChange用于检测页码数的改变
后端实现
这里的分页本质上与后端没有任何关系,每次分页时并未向后端请求对应页码的数据,仅在已有数据中进行截取。
当总数据较多时,可以在handleSizeChange与handleCurrentChange中实时从后端获取数据。
最终实现的页面效果如下
8、表单提交
表单实现
以下表单所绑定的为json对象:model="ruleForm"
,故此v-model="ruleForm.name"
其el-form-item所绑定的为ruleForm.name,同时还:rules="rules"
绑定了验证规则rules,ref="ruleForm"
表单被命名为ruleForm。
由submitForm事件提交表单
html
<el-form :model="ruleForm" :rules="rules" ref="ruleForm"
style="padding: 30px;width:400px;background-color: bisque;" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="name">
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="密码" prop="pwd">
<el-input type="password" v-model="ruleForm.pwd"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">立即登录</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
表单验证及提交
ruleForm对象为表单所绑定的数据模型
rules为表单具体字段的验证规则,针对每一个字段都可以设置多条规则
submitForm函数实现表单的验证及提交
js
export default {
name: 'login',
data() {
return {
ruleForm: {
name: '',
pwd: '',
},
rules: {
name: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
pwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
}
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {//表单验证成功,进入后台主页
this.$router.push({name:'mainframe'});
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}