Object.keys
在内部会根据属性名key
的类型进行不同的排序逻辑。分三种情况:
- 如果属性名的类型是
Number
,那么Object.keys
返回值是按照key
从小到大排序 ‘1’也算是number
- 如果属性名的类型是
String
,那么Object.keys
返回值是按照属性被创建的时间升序排序。
- 如果属性名的类型是
Symbol
,那么逻辑同String
相同
解构赋值
可以取代 delete xxx
1 2 3 4 5 6 7
| const { name,...rest } = { name:'z', age:10, sex:'female' }
const [ item,...rest ] = [ { first:'a' }, 23, 55 ]
|
json简写
key
和value
名字一样的时候可以省略value
1 2 3 4 5 6 7
| let name = 'zz' let age = 10
let json = { name, age, say(){ console.log('') } }
|
JavaScript浮点数运算精度问题
描述
一开始看到百度的部分解决方案是通过扩大N倍换为整数,但是亲测有问题。直接乘10的N次方部分数据还是会出现精度问题。
解决
- 我是通过先转换成字符串、然后去掉小数点转为整数
- 两个数之间小数点位数进行比较、少的在乘10的n-m次方,运算后在除以10的Math.max(n,m)
目前没发现bug、不确定是正确的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
function floatAddOrMinus(type: number, arg1: string, arg2: string) { let len1 = 0 let len2 = 0 let m = 0 let item1 = 0 let item2 = 0; try { len1 = arg1.split(".")[1].length; } catch (e) { len1 = 0; } try { len2 = arg2.split(".")[1].length; } catch (e) { len2 = 0; }
if (len1 > len2) { m = len1; item1 = 0; item2 = len1 - len2; } else { m = len2; item1 = len2 - len1; item2 = 0; }
if (type === 1) { return ( (Number(arg1.replace(".", "")) * 10 ** item1 + Number(arg2.replace(".", "")) * 10 ** item2) / 10 ** m ); } else { return ( (Number(arg1.replace(".", "")) * 10 ** item1 - Number(arg2.replace(".", "")) * 10 ** item2) / 10 ** m ); } }
|
vue3中ref和其他属性绑定值重名导致绑定失效
群友遇到的问题、我一开始看着也没觉得哪里不对。感觉以后能用的上,先存着 。
描述
使用element-plus
中的 el-form
的时候,model绑定了formData
,但是在页面上对表单进行操作的时候,数据绑定无效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <el-form ref="formData" :model="formData" :rules="rule"> <el-row justify="center"> <el-col :span="12"> <el-form-item label="入库类型" prop="inOutType"> <el-select v-model="formData.inOutType" clearable> <el-option label="外购" value="外购"></el-option> <el-option label="其他" value="其他"></el-option> </el-select> </el-form-item> </el-col> </el-row> </el-form>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| setup(){ let formData: IEmptyObject = reactive({ warningUseTime: 0, typeName: '', categoryCode: '', categoryName: '', maintenanceCode: '', maintenanceName: '', model: '', attribute: '', unit: '', warningProductionQuantity: 0 });
return { formData } }
|
错误原因
ref
绑定的内容和model
绑定的内容重复了,vue3中ref
绑定的内容也是通过在setup
中定义变量进行获取。具体原因还没仔细看,估计是ref的优先级更高?
proxy多个路由代理
重写失效、请求路径包含某个 代理名 代理失效。
记下 还没解决
哈希路由引起样式问题
在一个页面引入了样式,并且添加了 scoped
,但是在进行页面跳转的时候,这些引入的样式会影响另一页面。刷新之后就好了
初步猜测是因为路由用的哈希模式
的原因
hash
值变化不会导致浏览器向服务器发出请求
所以在第一个页面加载的样式,在跳转之后没有刷新,样式就一直会存在,因此影响到了页面的样式
解决方法
emit
父子组件通讯,点击事件触发后、强制刷新
- 监听
hash
值的变化、变化之后、强制刷新
1 2 3 4 5 6 7 8 9 10 11 12
| setup: () => { const route = useRoute(); watch( () => route.path, (to, from) => { if (from.includes("papercss") && from !== to) { location.reload(); } } ); }
|
el-date-picker限制时间选择范围
两个时间选择器、开始时间与结束时间的时间选择范围为24h
,并且精确到分
(format="yyyy-MM-dd HH:mm"
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <el-form-item prop="beginDateStr" label="开始时间"> <el-date-picker v-model="formData.beginDateStr" type="datetime" placeholder="选择日期时间" format="yyyy-MM-dd HH:mm" > </el-date-picker> </el-form-item> <el-form-item prop="endDateStr" label="结束时间"> <el-date-picker v-model="formData.endDateStr" type="datetime" format="yyyy-MM-dd HH:mm" placeholder="选择日期时间" > </el-date-picker> </el-form-item>
|
Picker Options 配置
开始时间限制
首先对开始时间进行限制 限制在当前日期之前;并且当开始日期改变的时候,结束日期清空
disabledDate 日期禁用范围
1 2 3 4 5 6 7 8
| <el-date-picker v-model="formData.beginDateStr" type="datetime" placeholder="选择日期时间" format="yyyy-MM-dd HH:mm" :picker-options="pickerOptionsStart" @change="handleChangeStart" ></el-date-picker>
|
1 2 3 4 5 6 7 8 9
| private pickerOptionsStart = { disabledDate: (time: Date) => { return time.getTime() > Date.now(); }, }
private handleChangeStart() { this.formData.endDateStr = ''; }
|
结束时间限制
因为是24h限制、所以 开始时间+24h 和 开始时间-24h 的时间都得禁用;精确到分钟,小时和分钟也得进行限制
selectableRange 时间选择范围
这个属性没有在el-date-picker
里面,在el-time-picker
里面,个人觉得文档写的不是很人性…
因为跨天的话、时间范围是不一样的 比如开始时间是2021-05-31 02:00
那么结束时间的范围是2021-05-31 02:00 - 2021-06-01 02:00
如果选的是31号 则 selectableRange = '02:00-23:59'
如果选的是1号 则 selectableRange = '00:00-02:00'
所以还得对日期选择进行监听,本来是想通过点击/change事件进行监听的
但是无效,然后通过监听input
框内数据的变化 来进行监听
1 2 3 4 5 6 7 8 9 10 11
| <el-date-picker v-model="formData.endDateStr" type="datetime" format="yyyy-MM-dd HH:mm" placeholder="选择日期时间" @input="handleChangeInputDate($event)" :picker-options="{ disabledDate: (time) => hanldeDisabledDate(time), selectableRange: dafaulttime, }" ></el-date-picker>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| private dafaulttime: string = '00:00:00-23:59:59';
private handleChangeInputDate(e: Date) { if (this.formData.beginDateStr) { const begin = new EasyDate(this.formData.beginDateStr).format('dd'); const end = new EasyDate(e).format('dd'); if (begin === end) { this.dafaulttime = new EasyDate(this.formData.beginDateStr).format('HH:mm:ss') + '-23:59:59'; } else { this.dafaulttime = '00:00:00-' + new EasyDate(this.formData.beginDateStr).format('HH:mm:ss'); } } }
private hanldeDisabledDate(time: Date) { if (this.formData.beginDateStr) { const pickerMinDate = new Date(this.formData.beginDateStr).getTime(); const maxTime = pickerMinDate + 8.64e7; const minTime = pickerMinDate - 8.64e7; return time.getTime() >= maxTime || time.getTime() <= minTime; } else { return time.getTime() > Date.now(); } }
|
针对daterange
和datetimerange
类型进行时间限制
不仅仅需要配置disabledDate
,还需要配置onPick
获取当前点击的日期
onPick Function({ maxDate, minDate }) 选中日期执行的回调,只选择一个的时候返回的minDate
实例:只能选择31天的范围
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <span>起止时间:</span> <el-date-picker style="width: 240px; margin-right: 10px" v-model="dateRange" type="datetimerange" range-separator="至" value-format="yyyy-MM-dd HH:mm:ss" start-placeholder="开始日期" end-placeholder="结束日期" @change="dateChange" :picker-options="{ disabledDate: (time) => hanldeDisabledDate(time), onPick: (time) => hanldeOnPick(time), }" :clearable="false" ></el-date-picker>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| private hanldeOnPick(e: IEmptyObject) { if (!e.maxDate) { const timeRange = 8.64e7 * 31; this.pickDateRange.maxTime = e.minDate.getTime() + timeRange; this.pickDateRange.minTime = e.minDate.getTime() - timeRange; } else { this.pickDateRange.minTime = null; this.pickDateRange.maxTime = null; } }
private hanldeDisabledDate(e: Date) { const pickerDate = e.getTime(); if (this.pickDateRange.minTime && this.pickDateRange.maxTime) { return ( e.getTime() <= this.pickDateRange.minTime || e.getTime() >= Date.now() || e.getTime() >= this.pickDateRange.maxTime ); } else { return e.getTime() >= Date.now(); } }
|
主要问题
结束时间的 picker-options
属性,如果直接通过一个对象传递的话 ,会失效..,不清楚原因。我猜测是双向数据绑定相关的东西的问题
1 2 3 4 5 6 7 8 9 10 11 12 13
| :picker-options="{ disabledDate: (time) => hanldeDisabledDate(time), selectableRange: dafaulttime, }"
:picker-options="pickerOption"
private pickerOption = { disabledDate: (time) => hanldeDisabledDate(time), selectableRange: dafaulttime, }
|
一般的接口请求都是以json的形式进行传输、这次的表单会有文件上传的情况 所以用formdata的形式进行传输。
表单数据存在body内 且content-type需要设置为application/json,文件数据存在file内

- formData请求,参数必须为FromData类型的
1 2 3 4 5 6
| let params = new FormData()
params.append('file',value,name)
|
- 对于不是文本/二进制类型的数据,还需要使用Blob对象进行转换
如上图所示,body
内传递的是Object
对象,而且,body
的content-type
需要设置为application/json
类型
1 2 3 4 5
| let obj = {...} let blob = new Blob([JSON.stringify(obj)],{type:'application/json'})
params.append('body',blob)
|
- axios主要配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| const instance = axios.create({ timeout: 600000, headers: { 'Content-Type': 'application/json' }, baseURL: '/', });
instance.upload = (url, data, config = {}, params) => { const formData = new FormData(); data.forEach(item => { formData.append('file', item.value, item.name || item.filename); }); if (params && Object.keys(params).length > 0) { for (const m in params) { if (params.hasOwnProperty(m)) { const key = m; const value = params[m]; formData.append(key, value); } } } return instance.request({ method: 'post', ...config, url, data: formData, }); };
instance.interceptors.request.use(config => { const { params = {} } = config; config.params = { ...params, time: new Date().getTime() }; config.headers = { ...(config.headers || {}), 'X-Auth-Token': CookieStorage.token, 'X-Stargate-AppId': 25, }; return config; }, err => { } );
export function uploadFile(path: string, file: IUploadParam[], config?: AxiosRequestConfig, params?: IEmptyObject) { return http.upload(path, file, config, params).then(res => { return Promise.resolve(res.data); }); }
uploadFile( this.path, (this.$refs.imageUpload as any).fileList, {}, { body: new Blob( [ JSON.stringify({ ...this.formData, factory: this.factory, workshop: this.workshop, }), ], { type: 'application/json' } ), } )
|
axios实现文件导出功能,无法获取response的异常信息

如图所示: 上方是调文件导出接口,返回的异常信息。下方是普通请求获取的异常信息。上方的data
内没有errorMsg
错误原因
可以看到上方红圈内的data
是Blob
类型的(文件存储类型),所以不能直接获取,需要FileReader
对象进行处理,转换获取blob、file文件的数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| instance.interceptors.response.use(response => { return Promise.resolve(response); }, error => { if (error && error.response && error.response.status) { let errCode = 0; let errMsg = ''; if (!!error.response.data) { if (error.response.config.responseType === 'blob') { const reader = new FileReader(); reader.readAsText(error.response.data); reader.onload = () => { try { const { errorMsg } = JSON.parse(reader.result as string); errMsg = errorMsg; handleError(error.response.status, errMsg); } catch (error) { console.log('解析错误'); } }; } else { const { status, errorMsg } = error.response.data; errCode = status; errMsg = errorMsg; handleError(error.response.status, errMsg); } } } return Promise.reject(error); });
|