1. input输入框保存对象格式的数据
有时候需要将JavaScript对象(或数组)格式的数据利用表单保存起来,但是输入框会将输入的对象数据当作字符串,这样存到数据库中的数据格式也是字符串。
例如:
// input输入框中输入的是 { name: 'snail', age: 20 }
// 表单提交时,该条数据就是 "{name: 'snail', age: 20 }"
针对这种使用场景,开发时可以从两个方面入手:
- 利用input保存数据前,将要保存的数据转为标准的JSON格式,再复制到输入框中,这样在使用保存的该条数据时,可以直接使用
JSON.parse()
转换为JavaScript对象或数组。// JSON字符串 let o1 = '{ "name": "snail", "age": 20 }' console.log(JSON.parse(o1)); // 可以被转成JavaScript对象 { name: 'snail', age: 20 } // “数组”的JSON数据 let a1 = "[1234, 4324, 432]" console.log(JSON.parse(a1)); // 可以被转成JS数组 [1234, 4324, 432] // “数组”的JSON数据 let a2 = '[{"name": "jack", "age": 13 }, { "name": "mike", "age": 15 }]' console.log(JSON.parse(a2)) // 可以被转成数组 [{name: 'jack', age: 13}, {name: 'mike', age: 15}] // 多层JSON数据 let o2 = '{ "name": "snail", "age": 20, "other": { "sex": "male", "address": "上海市黄浦区人民广场" }}' console.log(JSON.parse(o2)); // 可以被转成对象 { age: 20, name: "snail", other: { sex: 'male', address: '上海市黄浦区人民广场' } }
- 一些字符串数据格式不符合标准的JSON格式,直接使用
JSON.parse()
会报错,这时可以使用eval()
来进行格式转换let o3 = "{ name: 'snail', age: 20, other: { sex: 'male', address: '上海市黄浦区人民广场' }}" console.log(JSON.parse(o3)); // 报错:Uncaught SyntaxError: Unexpected token n in JSON at position 2 // 使用eval(),为了避免eval()解析对象时将其当做语句执行,需要在对象字符串外使用()包裹,转换数组时,无需加() console.log(eval('(' + o3 + ')')) // 可以正常转换
2. 苹果IOS中Date的兼容性问题
2001-01-01 12:00:00
这种格式使用new Date()
时,会报错,需要转变为2001/01/01 12:00:00
格式
let date = '2001-01-01 12:00:00';
console.log(new Date(date)); // IOS系统中报错 invalid Date
date = date.replace(/-/g, '/')
console.log(new Date(date)); // IOS中正常
3. 生成海报图片发生错位/偏移问题
原来使用的是html-2-canvas
库,版本较旧,改用新库html-to-image
完美解决问题。文档地址
4. Vue项目过渡行为和滚动行为的冲突问题
项目中使用transition
组件来实现组件的过渡行为,同时也使用vue-router
中的scrollBehavior
定义了滚动行为。
<transition name="fade-transform">
<keep-alive>
<router-view :key="key" />
</keep-alive>
</transition>
const createRouter = () =>
new Router({
mode: 'hash',
scrollBehavior: (to, from, savedPosition) => {
if (savedPosition) {
return new Promise(resolve => {
setTimout(()=>{
resolve(savedPosition)
}, 500)
})
} else {
return { y: 0 }
}
},
routes
})
export default createRouter()
实测下来,在已发生滚动的页面切换至别的页面时,滚动条首先会被置顶,之后出现页面过渡效果,然后进入新页面。返回旧页面时,没有自动回退到之前的滚动位置。
禁用过渡组件后,返回页面时是可以自动到达之前的滚动位置的。
这应该是过渡组件transition
导致组件加载被延迟,滚动行为没有正确作用到组件上,所以没有达到滚动位置被记录的效果。
解决方案:
【已测试】
scrollBehavior
中使用延迟滚动,同时设置一下scroll-behavior
样式。const createRouter = () => new Router({ mode: 'hash', scrollBehavior: (to, from, savedPosition) => { return new Promise((resolve) => { // 这里的延迟时间根据过渡时间来决定,>过渡时间即可 setTimeout(() => { resolve(savedPosition ? savedPosition : { y:0 }) }, 1000) }) }, routes }) export default createRouter()
平滑滚动,目前除了
IE
浏览器,主流浏览器都已经支持。html { scroll-behavior: smooth; }
【待测试】使用
vue-router-view-transition
组件替换transition
组件替换【已测试,无效】
history
路由模式下,设置history.scrollRestoration = 'manual'
【待测试】自定义过渡动画,弃用
transition
组件
5. Canvas设置window.innerHeight
时出现滚动条的问题
项目中利用Three.js
做全屏3D模型,分别给canvas设置window.innerWidth
和window.innerHeight
作为宽高,发现始终在竖直方向上会出现
滚动条,这就导致水平方向上也会出现滚动条(因为innerWidth是包含滚动条的宽度)。
解决办法:
- 确保
body
元素的margin
被清零 - 给
canvas
元素设置display: block;
,或给canvas
的父元素设置font-size:0;
以确保元素之间的间隙被清零 - 电脑屏幕设置了缩放的情况下(我的缩放是125%),
window.innerHeight
高度是窗口理论缩放高度原始innerHeight/devicePixelRatio
四舍五入
后的结果,所以window.innerHeight
有可能大于理论缩放高度,这就导致设置了滚动条的出现。
我这里进行了一定抹零处理。如果想省事也可以直接window.innerHeight - 0.5
。const { innerWidth, innerHeight, devicePixelRatio } = window; // 现在电脑的高分辨率屏幕一般都会设置缩放(我的屏幕设置了125%) // 此时window.innerHeight = Math.round(理论上屏幕缩放后分辨率) // 这时候如果给元素设置的高度 = window.innerHeight,可能就会出现滚动条 // 这里利用devicePixelRatio计算一下window.innerHeight缩放前的高度(这是一个近似之后的值) // 对缩放前的高度抹零后再计算缩放值,这样就能保证永远不会出现滚动条 const canvasHeight = (Math.floor(innerHeight * devicePixelRatio) / devicePixelRatio).toFixed(2); renderer.setSize(innerWidth, canvasHeight); // 设置渲染区域尺寸
6. 长列表优化
- 时间分片(适用于简单dom)
- 按照一定的时间间隔来分批渲染数据,避免数据同时一次性插入过多dom导致页面卡顿,常用的实现是通过
requestAnimationFrame
和DocumentFragment
来间歇性的渲染dom
- 按照一定的时间间隔来分批渲染数据,避免数据同时一次性插入过多dom导致页面卡顿,常用的实现是通过
- 虚拟列表(适用于复杂dom)
- 只对可见区域进行渲染,对非可见区域中的数据利用等高的占位元素来替代,从而减少页面中的DOM节点数量,以提升渲染速度
💡「前端进阶」高性能渲染十万条数据(虚拟列表)
💡「前端进阶」高性能渲染十万条数据(时间分片)
7. Vue兼容IE8及以下版本的策略
目前看来确实无法兼容,可以使用司徒正美的avalon.js, 兼容到IE6
8. 不同浏览器的兼容性问题解决
CSS兼容
- 使用
reset.css
重置样式表或Normalize.css
,统一各浏览器的基础样式,比如margin
、padding
、font-size
等 - 使用
PostCss
插件autoprefixer
,自动补全css浏览器前缀,解决部分浏览器中css属性不一致的问题。
js兼容
- 事件监听绑定和移除的兼容问题(绑定:
addEventListener
和IE:attachEvent
,移除:removeEventListener
和IE:detachchEvent
),要先判断再使用 - 事件对象的兼容问题(event),IE8及以下浏览器中,将event放在了window.event属性下,所以要使用
event || window.event
- 键盘的键值码,
keyCode
和IE的which
- 阻止事件的默认行为的兼容问题,
preventDefault
和IE的returnValue
- 阻止事件冒泡的兼容问题,
stopPropagation
和IE的cancelBubble
new Date()
构造函数使用,2019-12-09
是有问题的,要转换为2019/12/09
document.documentElement
兼容,要使用document.documentElement || document.body
9. npm install报错问题
基于uni-app + vue2
开发的项目,在使用npm install
报错python
找不到, npm run dev
报错mustache
找不到
原因:node版本问题
解决办法:npm install
要在node@13.6.0
下,npm run dev
需要在node@16.13.1
下,至于为什么npm install
和npm run dev
需要在不同的node版本下,有待研究。