- 使用 URL.createObjectURL 预览
URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的 URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。用法用下:
objectURL = URL.createObjectURL(object);
其中,object 参数指 用于创建 URL 的 File 对象、Blob 对象或者 MediaSource 对象。
对于我们的 input[type=file] 而言, input.files[0] 可以获取到当前选中文件的 File 对象。示例代码如下:
<input id="inputFile" type="file" accept="image/*">
<img src="" id="previewImage" alt="图片预览">
<script>
const $ = document.getElementById.bind(document);
const $inputFile = $('inputFile');
const $previewImage = $('previewImage');
$inputFile.addEventListener('change', function() {
const file = this.files[0];
$previewImage.src = file ? URL.createObjectURL(file) : '';
}, this);
</script>
常见的图片上传同步渲染
onIptChange (e) {
// console.dir(e.target)
if (e.target.files.length === 0) {
// 没有图片
this.avatar = ''
} else {
// 选择了一张图片 图片对象--> base64 格式的字符串
// e.target.files[0]
// 1. new dileReader() 文件读取器(浏览器自带的)
const reader = new FileReader()
// 2.读取图片对象
reader.readAsDataURL(e.target.files[0])
// 3. 监听onload文件读取完毕事件
reader.onload = () => {
// console.log(reader.result)
// 头像预览赋值
this.avatar = reader.result
}
}
},
<template>
<el-card class="box-card">
<template v-slot:header>
<div class="clearfix">
<span>更换头像</span>
</div>
</template>
<div>
<!-- 图片,用来展示用户选择的头像 -->
<img :src="avatar" alt="" v-if="avatar"/>
<img src="@/assets/images/avatar.jpg" v-else/>
<!-- 按钮区域 -->
<div class="btn-box">
<!-- 1.书写input:file的表单项,并且让他隐藏 -->
<input type="file" accrpt="image/*" style="display:none" ref="iptRef" @change="onIptChange">
<el-button type="primary" icon="el-icon-plus" @click="chooseImg" >选择图片</el-button>
<el-button type="success" icon="el-icon-upload" :disabled="avatar===''" @click="uploadImg" >上传头像</el-button>
</div>
</div>
</el-card>
</template>
<script>
export default {
data () {
return {
avatar: ''
}
},
name: 'UserAvtatar',
methods: {
chooseImg () {
this.$refs.iptRef.click()
},
onIptChange (e) {
// console.dir(e.target)
if (e.target.files.length === 0) {
// 没有图片
this.avatar = ''
} else {
// 选择了一张图片 图片对象--> base64 格式的字符串
// e.target.files[0]
// 1. new dileReader() 文件读取器(浏览器自带的)
const reader = new FileReader()
// 2.读取图片对象
reader.readAsDataURL(e.target.files[0])
// 3. 监听onload文件读取完毕事件
reader.onload = () => {
// console.log(reader.result)
// 头像预览赋值
this.avatar = reader.result
}
}
},
async uploadImg () {
// 4.图片上传
const {
data: res } = await this.$http.patch('/my/update/avatar', {
avatar: this.avatar })
// console.log(res)
if (res.code !== 0) return this.$message.error('上传头像失败!')
this.$message.success('上传成功')
// 再次通知vuex获取用户信息 // 上传头像成功
this.$store.dispatch('initUserInfo')
}
}
}
</script>
<style>
</style>
es6之扩展运算符 三个点(…) es6之扩展运算符 三个点(…) 对象的扩展运算符 数组的扩展运算符
理解对象的扩展运算符其实很简单,只要记住一句话就可以:
对象中的扩展运算符(…)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
// 解决方案 两种 都相当于浅拷贝
// 1. 浅拷贝 Object.assign({},this.$store.state.userinfo)
// 2. 扩展运算符 userForm: { ...this.$store.state.userinfo },
let bar = {
a: 1, b: 2 };
let baz = {
...bar }; // { a: 1, b: 2 }
上述方法实际上等价于:
let bar = {
a: 1, b: 2 };
let baz = Object.assign({
}, bar); // { a: 1, b: 2 }
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。(如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性)。
同样,如果用户自定义的属性,放在扩展运算符后面,则扩展运算符内部的同名属性会被覆盖掉。
let bar = {
a: 1, b: 2};
let baz = {
...bar, ...{
a:2, b: 4}}; // {a: 2, b: 4}
利用上述特性就可以很方便的修改对象的部分属性。在redux中的reducer函数规定必须是一个纯函数(如果不是很清楚什么是纯函数的可以参考这里),reducer中的state对象要求不能直接修改,可以通过扩展运算符把修改路径的对象都复制一遍,然后产生一个新的对象返回。
这里有点需要注意的是扩展运算符对对象实例的拷贝属于一种浅拷贝。肯定有人要问什么是浅拷贝?我们知道javascript中有两种数据类型,分别是基础数据类型和引用数据类型。基础数据类型是按值访问的,常见的基础数据类型有Number、String、Boolean、Null、Undefined,这类变量的拷贝的时候会完整的复制一份;引用数据类型比如Array,在拷贝的时候拷贝的是对象的引用,当原对象发生变化的时候,拷贝对象也跟着变化,比如:
let obj1 = {
a: 1, b: 2};
let obj2 = {
...obj1, b: '2-a'};
console.log(obj1); // {a: 1, b: 2}
console.log(obj2); // {a: 1, b: "2-a"}
上面这个例子扩展运算符拷贝的对象是基础数据类型,因此对obj2的修改并不会影响obj1,如果改成这样:
let obj1 = {
a: 1, b: 2, c: {
nickName: 'd'}};
let obj2 = {
...obj1};
obj2.c.nickName = 'd-a';
console.log(obj1); // {a: 1, b: 2, c: {nickName: 'd-a'}}
console.log(obj2); // {a: 1, b: 2, c: {nickName: 'd-a'}}
这里可以看到,对obj2的修改影响到了被拷贝对象obj1,原因上面已经说了,因为obj1中的对象c是一个引用数据类型,拷贝的时候拷贝的是对象的引用。
数组的扩展运算符
扩展运算符同样可以运用在对数组的操作中。
可以将数组转换为参数序列
function add(x, y) {
return x + y;
}
const numbers = [4, 38];
add(...numbers) // 42
可以复制数组用扩展运算符
const arr1 = [1, 2];
const arr2 = [...arr1];
还是记住那句话:扩展运算符(…)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中,这里参数对象是个数组,数组里面的所有对象都是基础数据类型,将所有基础数据类型重新拷贝到新的数组中。
扩展运算符可以与解构赋值结合起来,用于生成数组
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
需要注意的一点是:如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
扩展运算符还可以将字符串转为真正的数组
[...'hello']
// [ "h", "e", "l", "l", "o" ]