- A+
环境:Nuxt.js(Vue全家桶+webpack+bable)
组件库:element.ui
插件适用场景:脱离了页面布局的交互页面,类似于对话框、抽屉
全局调用插件的实现原理:
- 利用element.ui的dialog组件,实现页面的显示、关闭
<template>
<el-dialog :visible.sync="show">
<button @click="close">取消</button>
<button @click="sure">确定</button>
</el-dialog>
</template>
name: "ImgUpload",
props: {
//将vue实例传入,this指针。若组件内有使用Vue实例的数据或方法,则此参数为必须
that: {
type: Object
}
},
data() {
return {
show: false,
}
},
methods:{
//初始化
confirm() {
this.show = true;
return new Promise((resolve, reject) => {
this.promiseStatus = { resolve, reject };
});
},
//取消,关闭页面
close(){
this.show = false;
//点击取消后在此传数据给页面
this.promiseStatus && this.promiseStatus.reject(//数据)
},
//确定,关闭页面
sure(){
this.show = false;
//点击确定后在此传数据给页面
this.promiseStatus && this.promiseStatus.resolve(//数据)
}
}
- 将写好的vue组件以函数的形式挂载到vue原型上
import Vue from "vue";
import ImgUpload from "./ImgUpload.vue";
const Vuecomponent = Vue.extend(ImgUpload);
const vm = new Vuecomponent().$mount();
let init = false;
const install = options => {
Object.assign(vm, options);
if (!init) {
document.body.appendChild(vm.$el);
init = true;
}
return vm.confirm();
};
export default install;
import ImgUpload from "@/components/ImgUpload.js";
Vue.prototype.$imgUpload = ImgUpload;
- 调用方式
<template>
<button @click="imgUpload">选择相片</button>
</template>
<script>
export default {
methods: {
imgUpload(){
this.$imgUpload({that:this}).then(res=>{console.log(res);});
},
}
};
</script>
服务器签名,web端直接上传图片至阿里云OSS
web端上传文件至阿里云OSS的三种方式,及相关规则限制如下
[web端上传数据到阿里云OSS] https://help.aliyun.com/document_detail/112718.html?spm=a2c4g.11186623.6.1711.51e04d52TZwRRY
[服务端签名后直传] https://help.aliyun.com/document_detail/31926.html?spm=a2c4g.11186623.6.1718.8ecd6843ilGhvQ
[PostObject] https://help.aliyun.com/document_detail/31988.html?spm=a2c4g.11186623.2.12.6a0a6843Vt9fM9#reference-smp-nsw-wdb
本文采用的方式是PostObjecj,通过HTML表单上传的方式将文件(Object)上传至指定存储空间(Bucket)。
因为阿里云的文件上传只能一张一张上传,且服务端每次传回的key值(文件路径)每次都会变动。所以,通过循环文件列表的方式,逐次向服务器请求签名,并以表单的形式上传至阿里云OSS,上传完成之后,再统一将图片路径传回给服务器。
注1:因为服务器传回的host地址可能变更,所以,本文没有将host地址配置进nuxt的全局环境中。
注2:为了代码编写,axios配置了前缀/api,所以,采用了原生ajax。
<script>
export default {
methods: {
//用户选择好了图片并点击上传
upload() {
let vim = this.that;
let _this = this;
//上传前向服务器发起请求,询问是否能上传
vim.$canUpload({ album_id: this.album_id }).then(res => {
if (res.data.code === 200) {
postObject();
} else {
vim.$message.info("该相册不可上传图片");
}
});
//利用formData上传至阿里OSS
function postObject() {
_this.uploadPicFile.forEach((pic, index) => {
vim.$getOSS().then(secret => {
let SECRET = secret.data;
let filename = "-" + pic.width + "*" + pic.height + pic.type;
let formData = new FormData();
formData.append("key", SECRET.key + filename); //存储在oss的文件路径+文件名
formData.append("OSSAccessKeyId", SECRET.accessid); //accessKeyId
formData.append("policy", SECRET.policy); //policy
formData.append("Signature", SECRET.signature); //签名
formData.append("success_action_status", 200); //成功后返回的操作码
formData.append("file", pic.file); //文件
let xhr = new XMLHttpRequest();
xhr.open("POST", "https://" + SECRET.host, true);
xhr.onload = function() {
if (xhr.status === 200) {
pic.wholePath = SECRET.host + "/" + SECRET.key + filename; //图片全路径
} else {
vim.$message.error("部分图片上传失败");
}
//上传完最后一张后统一将图片信息传给服务器
if (index === _this.uploadPicFile.length - 1) {
postPicInfo();
}
};
xhr.send(formData);
});
});
}
//将图片路径及相关信息统一传给服务器
function postPicInfo() {
let successPics = _this.uploadPicFile.filter(ele => {
return Object.keys(ele).includes("wholePath");
});
let data = {};
successPics.forEach((pic, index) => {
data[`insert[${index}][pic_name]`] = pic.name;
data[`insert[${index}][pic_desc]`] = pic.name;
data[`insert[${index}][album_name]`] = _this.albumName;
data[`insert[${index}][album_id]`] = _this.albumId;
data[`insert[${index}][pic_url]`] = pic.wholePath;
});
vim.$addPic(data).then(res => {
if (res.data.code === 200) {
vim.$message.success("图片上传成功");
}
});
}
}
}
};
</script>
可思考方向:采用antd组件库的upload组件等。
- 我的微信
- 这是我的微信扫一扫
-
- 我的微信公众号
- 我的微信公众号扫一扫
-