项目规范
1
需要循环的内容必须要经过判断,由外至里的判断防止循环报错。此外不循环的变量也要做无值处理
2
所有的图片给定父级高宽并设置默认背景站位图,给自身宽百分百。
3
所有关于后台生成的文字都要做文字溢出处理
4
在处理state的问题上,用函数改变state。用箭头函数来规避this指向问题。
state = { isOnOver: false };
onSwitch = () => {
this.setState(pre => ({ isOnOver: !pre.isOnOver }));
};
//pre表示原state
5
在flex布局中最好不要写死宽度采用百分百的形式,全部设为块级元素,防止iebug。
6
利用取反,来减少代码量。如鼠标进入事件和离开事件。
8
在函数需要参数时要
onClick={() => this.handClick("new")}这种形式。
9
在react中多使用三元表达式,另外一元表达式也很重要。重要的是减小冗余。
10
isShow? 123 :null
这种三元表达式有返回空值时直接用 isShow&&123 这种一元表达式。
11
在类名判断的时候注意不要返回null会增加一个新的名为null的类名
class=“${ isHot? "123" :"这里面写空字符不要写null"}
12
在react中需要粘贴复制的东西都要考虑用组件来完成。
13
在使用 axios 进行 ajax 请求的时候,{responseType: "blob"}表示请求二进制文件,一般用于图片验证码。请求的二进制文件不能被img
标签的src
识别需要 URL.createObjectURL()对其进行创建 url。
如下:
const urlCreator = window.URL || window.webkitURL;
const imageUrl = urlCreator.createObjectURL(response);
14
在父级高度未确定的时候使用height:100%
是以自身高度为标准,这时候使用height:inherit
可参考这里
15
flex 布局中用flex:1
来表示剩余宽度的方式对文字类的内容溢出是无效的,也就是文字溢出时会超出剩余的宽度造成样式紊乱。实际上 flex 布局并没有想象的自带overflwo:hidden
的效果。事实上 flex 并不能解决文字溢出问题,仍然需要overflow:hidden
的方式解决。flex:1
的问题也同样这样解决。这里
xxx {
flex: 1;
overflow: hidden;
}
16
flex:none
表示展示自身高宽。不会被其他兄弟元素挤压缩小。
17
使用定位的元素要注意层级关系。注意浏览器未全屏是绝对定位元素的位置。
18
文字移除的省略号显示元素本身要有宽度,没有的宽度的可以设置max-width:100%
或者display:inline-block
因为在flex布局中text-overflow: ellipsis
是无效的。
max-width
设置时父级应有宽度。或用width:inherit
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
19
定位元素的垂直居中最好用
top: 50%;
transform: translateY(-50%);
不过使用百分比会有 21 的问题。
20
组件封装的时候传值,用...rest 代替不重要的参数。rest 必须写在最后。
export default ({ ver, hor, btnClass, path, icoClass, con, ...rest }) => (
);
21
该问题实在实现定位元素垂直居中是遇见的。这里
如果元素高度为奇数是,transform:translate(10%)
的参数又是百分比时会造成字体抖动和模糊,因为在计算距离时有小数。字体渲染会出问题。解决办法有 1.元素高度或宽度设置偶数。 2.translate()
参数设置为具体数值。 3.为了垂直居中嵌套一个高度height:100%
的父级。给父级设置flex
实现居中。
在 react 的路由跳转时想要跳到具体某个锚点时在路由地址位置后加入#id
。例如/home#id
overflow:hidden
在解决元素没有宽度的时候有很大用处。主要是出发了 BFC。
flex 布局中可能会有高度和宽度失效的情况(只是不能获取数值),这取决于主轴方向,横向没高度,竖向没宽度.
这个时候flex:1
或其他子元素的子元素都不能使用height:100%
.
有时候要灵活运用 max-height 和 min-height.
设置 min-height 的元素的子元素不能使用height:100%
.
height:100%
一定要实现除了给父级写死高度外。可以使用定位的方法。即父级相对定位子级绝对定位。
在 react 中进行属性传值如果要传false
可以xxx={false}
的形式。要传true
写上属性名字就行了例如
isrank 属性就是 true.
在变量获取不到的时候,先要检查变量名是否重复。
阴影被隐藏的问题。一旦子元素的 width 挤满父元素,那么他的阴影就会被父元素(左右)盖住。
所有在写阴影的时候最好四周都有边距。
overflow:hidden
是针对于 paddingbox 的,所有子元素的 border 会被覆盖,边框阴影更不用说了。
与
的
display
是不一样的。inline
的元素决定它宽度的只有字符的多少如果子元素为块级元素那它的宽度不会被块级元素撑大它的宽度就是父级的宽度。而inline-block
却不同 它有块级元素的特点不会受父级的影响。
数字和文字天然不对齐,需要给数字100%以下的行高才能对齐。
在flex里面text-overflow: ellipsis;
无效。需要套一个父级。
在移动端背景图片要设置background-size:100%
server.use(
router.get("/plug/:id", (ctx, id) =>
renderAndCache(ctx, "/5-plug/2-detail", null, { id })
)
);
// 路由的:id表示匹配后面的一切,所以如果有"/plug/pay"类似的路由要写在这个前面,防止路由被覆盖。
37
彩色图标需要多个类名。因为彩色图标有多个icon组成
38
next 中使用Router进行路由跳转时要使用真实的路由地址,它是由第二个参数的,就是as
Router.push({
pathname: '/about', // 真实地址
query: { name: 'Zeit' }
},
"/about" // as地址
)
在reducers中检测返回值。
(action.payload && action.payload)
这段代码是检测了action是否存在然后返回。
在const还未引入之前,HOME_BANNERS这种大写的命名变量就表示常量。至今仍然沿用。
rem时根据根元素(html)的字体大小为标准的。引用阿里的高清方案在750px的设计图直接可以1px用0.0rem表示。em相对于父级元素的大小而调整的。
42
原则上所有的列表都是需要下拉刷新的。除了推荐列表。
在componentDidMount生命周期之前组件state要用的值要写上。componentDidMount是组件第一次render之后的事件。所以第一次render所需的值要先写上。
componentWillReceiveProps表示当props更新时,发生的事件。没有此事件每当props更新都是触发一次render。
react允许组件当成state值进行传递
state = {
tabs: [
{ title: " 课程", type: 1 },
{ title: "嘟嘟视角", type: 3 },
{ title: "插件", type: 2 }
],
presentNav: 0,
typeId: 1,
template: item =>
};
template(item)}
/>
使用取反判断时一定要记得加上!反义号。
window的方法能够被客户端捕捉到。在与app交互的时候使用自定义的全局函数来和app做交互。
href值为false时也能跳转
对于订单这种敏感的信息,必须先判断重要的信息比如价格。
50
componentDidMount不能设置state。
设置移动端的topbnav返回栏最好左右两边都设为函数。
在进行路由传值的时候不要直接用url传值应query防止路由地址污染。
正则选中所有的标签和标签内部的所有内容<[^>]+>/g
,img的内容
在html的规则中button内部是不能在嵌套button的。在eslint检查机制中只有a、button标签才能有点击事件。但在这种嵌套有为html规则的时候eslint就会以html标准为主即button里面的div可以加入点击事件。
当行高为100%时,且有overflow:hidden的时候 y、g这种下表字母就是被截断一部分,数字和文字是没有这个问题。
当img的src失效的时候会有一个无法消除的边框,当src等于null或者fasle的时候也同样出现。
ui图的粗字体在css中要加粗。
在编译模式上jsx语法错误不会显示,直接报错。jsx中style不能为空
对于无依赖的绝对定位一定不能写width:100%之类的高宽。先要确认其实际父级。
垂直无法居中的元素可以使用lh100和ptb5的方式实现垂直居中。
对于56这种情况最靠谱的方式还是判断img的src为false的时候渲染为一个div。当一个元素受限于html规则无法实现效果时首先想到的是如何替换它。
对于使用的React Slick插件来说它在移动端会出现img标签无法获取点击事件的bug。对于这种只针对于单独元素的bug且无法替换该元素可使用一个定位的同等大小的空div进行覆盖处理。
使用es6语法创建一个length不为0的空数组,total为数组length数。
const count = Array(...Array(total))
linear-gradient 是background-image的值,它不能有过渡transtion效果。
无论父级层级多少都要被子级所覆盖。
background缩写顺序
background: [background-color] [background-image] [background-repeat] [background-attachment] [background-position] / [ background-size] [background-origin] [background-clip];
text-ovflow-2在dom有padding的时候是无效的。
一个async 的异步函数内部可以允许多个异步等待
async fun (){
try{
const {a}=await get()
const {b}=await get()
}.catch(error) {
}
}
对于自己写的倒计时插件在定时器被移除时(由于执行顺序的原因是先移除在设置state)在赋值不存在的state的时候会报错,所以需要先设置定时函数,定期执行。在详情页我们也不能实时的获取订单等数据的状态。同样可以设置延迟函数的方式来实现。
在react加入dom事件,在componentDidMount里面绑定事件。全局绑定的事件一定要在组件卸载前移除。注意刷新页面不会执行componentWillUnmount事件但会执行componentDidMount。由于某些原因导致因为刷新重复绑定某些事件会失效,在移动端没有此问题。
componentDidMount() {
this.getCon();
const { delivery_type } = common.searchToObj();
if (delivery_type === "1") this.onAddress();
if (common.isAndroid) {
window.addEventListener("resize", this.footHide);
}
}
componentWillUnmount() {
if (common.isAndroid) {
window.removeEventListener("resize", this.footHide);
}
}
react获取dom的最好方法还是直接获取元素dom,组件的dom获取目前麻烦。目前有三个步骤。
this.myRef = React.createRef();
componentDidMount() {
this.myRef.current.xxx
}
123
1. 先在初次render之前设置要获取的dom的变量名
this.xxx=React.createRef()
2.在jsx中html内加入ref={this.xxx} 名字一致。
3.在componentDidMount或函数中就可以调用
还有一种更简单的方法就是
this.ref}>
this.ref就是dom对象但是在componentDidMout和componentDidUpdate之后才会存在其余时候都是null。
-
在安卓或出现软键盘遮挡页面内容的情况。解决办法有监测window的resize事件,来隐藏或制造margintop来实现与ios同步。此为安卓专属方法需先判断是安卓手机后才能调出。
window.addEventListener("resize", this.footHide);
注意!在即使加入安卓判断在微信里面还是ios有几率触发resize
。
最终的方法是不使用fixed。使用flex布局。中间的dom设置overflow-y:scroll
-
在ios下字体图标总是被切割,目前最好的方法就是加入pt5
-
在书写大量重复页面的时候要利用map。即使不是后台数据也可以自定义数组来map。总之当有大量重复内容的时候就是map来节省代码量。最典型的就是订单信息这样的表格。
-
当判断多余三个的时候就是需要swich的时候了。
-
在截取有效数据的时候可以采用filter的方式。
newArr = arr.filter(item=>判断条件)
-
当后台返回数据有数值型的话保险的做法就是全部paseInt()
-
当一个异步函数内部异步请求还包含异步。需要在内部设置一个异步对象。
let {data} = await new Promise((resolve, reject) => {
this.$refs[formName].validateField('tel', (valid) => {
if (!valid) {
this.loading = true
let query = {
data: {
type: 0,
mobile: this.form.tel
}
}
post_web_captcha(query).then(resolve, resolve)
} else {
resolve({data: {error: true, message: '请输入手机号!'}})
}
})
})
-
在一元运算符中undefined和null都不会被认为false。所有如下的
{item.buy_type !== 2 && item.launch_log_id && collageStatus
collageStatus即使是undefined就会返回undefined不会返回flase。所以不要是最后一项为undefined。
-
textarea标签的maxlength 属性写在最前面。否则会报错
-
writing-mode文字方向。
writing-mode: horizontal-tb;
horizontal-tb
内容从左到右水平流动,从上到下垂直流动。下一条水平线位于前一条线的下方。
vertical-rl
内容从上到下垂直流动,从右到左水平流动。下一条垂直线位于前一行的左侧。
vertical-lr
内容从上到下垂直流动,水平从左到右。下一条垂直线位于前一行的右侧。
sideways-rl
内容从上到下垂直流动,所有的字形,甚至垂直脚本中的字形,都被设置在右侧。
sideways-lr
内容从上到下垂直流动,并且所有的字形,甚至垂直脚本中的字形都被设置在左侧。
-
在react父组件是可以使用子组件的方法的。具体适用方法是
this.ref=ref}>
1. 在子组件里用ref获取实例绑定到父组件的this里面。
2. 子组件的方法都绑定到了this.ref里面。
3. 由于this的指向问题所以在父组件中以箭头函数的方式调用。
change=()=>this.ref.childFun()
-
在用户做出某些操作是需要增加一个边框,在box-sizing情况下页面会下移,这个时候只要先把边框设置为透明色即可。
-
next的getInitialProps 是服务器方法所以在浏览器的console是看不到的。也不能适用window对象。
-
在使用flex布局要一排显示三个且不知道总量的情况下可以使用父级伪类的方法加一个高为1px宽为子级宽度的伪类。
-
行内元素有在被挤压的时候会失去的字设定的宽度。当宽度小于文字占有宽度text-overflow-one 就会起作用。宽度仍然被缩小但是文字会被隐藏。
-
js默认为false的集中情况。
null,undefined,"",0,NaN,但是{},[]不会被当成false。
-
一个多年前的问题,在设置弹出框禁止全局滚动是,html的 overflow-y
只能是自适应。
-
在react中当一个组件被销毁的时候它的异步操作还没有完成就会报错。解决方法就是在componentWillUnmount设置一个值为ture然后组件内部所有的异步操作都先判断这个值为false才开始运行。参考,
-
在coding平台中是文件名是不区分大小写的所以严格规范,同理在win中相对路径也是不区分大小写。
-
对于一个ajax请求,当被catch捕捉错误基本是网络错误,接口错误。如果无法返回数据那就是参数不全面,前端应该加以限制禁止不全的参数参与到请求。
async fun = ()=>{
try{
const data = await http.get("xxx",{...})
if(data){
// ...
}else{
message.error(msg)
}
}.catch(error){
console.info(error)
}
}
-
分享地址
qzone
'http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url={url}&title={title}&pics={pic}&summary={content}'
weibo
'http://service.weibo.com/share/share.php?url={url}&title={title}&pic={pic}&searchPic=false'
tqq
'http://share.v.t.qq.com/index.php?c=share&a=index&url={url}&title={title}&appkey=801cf76d3cfc44ada52ec13114e84a96'
renren
'http://widget.renren.com/dialog/share?resourceUrl={url}&srcUrl={url}&title={title}&description={content}'
douban
http://www.douban.com/share/service?href={url}&name={title}&text={content}&image={pic}
facebook
'https://www.facebook.com/sharer/sharer.php?u={url}&t={title}&pic={pic}'
twitter
'https://twitter.com/intent/tweet?text={title}&url={url}'
linkedin
'https://www.linkedin.com/shareArticle?title={title}&summary={content}&mini=true&url={url}&ro=true'
weixin
'http://qr.liantu.com/api.php?text={url}'
qq
'http://connect.qq.com/widget/shareqq/index.html?url={url}&desc={title}&pics={pic}'
-
polyfill.io 按需加载babel自动监测浏览器是否需要babel转换
"https://cdn.polyfill.io/v2/polyfill.min.js"
95
function*表示generator函数,它可以返回多次。
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
foo()只是创建而非执行
var a=foo(1)
a.next() // {value: 2, done: false}
a.next() // {value: 3, done: false}
a.next() // {value: 4, done: true}
返回值为{value: 4, done: true}
96
对于使用哈希路由来解析地址中所带的值。
window.location.hash 指路由中"#"后边的地址。
-
在上传文件流的时候。需要创建一个FormData 对象,上传也是这个对象。
关于FormData
我们要上传的文件为
在react 中 file为e.target.files[0]。e.target.files是一个伪数组代表上传的文件。
在普通的html里面为表单dom的files[0]值。
把获取的file值加入FormData对象中进行上传。
var formData= new FormData()
formData.append("file",file),
http.post("",formData,).then()
-
读取文件获取图片的base64
//创建 文件读取对象
const reader = new FileReader();
//正在读取中,读取返回result为所需的base64
reader.addEventListener('load', () => callback(reader.result));
// 该方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成(DONE),并触发 loadend 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容
reader.readAsDataURL(img)
-
验证上传图片尺寸。
const reader = new FileReader();
//读取图片数据
reader.addEventListener("load", e => {
const data = e.target.result;
//创建图片实例
const image = new Image();
//加载图片获取图片真实宽度和高度
image.addEventListener("load", () => {
image.width; //图片宽度
image.height //图片高度
});
//给图片base64
image.src = data;
});
reader.readAsDataURL(file);
-
Form
-
在axios库有onUploadProgress的方法能够检测文件上传的进度
onUploadProgress:(progressEvent) => {
const {lengthComputable, loaded, total} = progressEvent
lengthComputable, //是否能够被读取长度
loaded// 已上传,
total //以下载
},
进度= math.round(loaded/total*100)
根据测试,该回调函数只会分段返回并不是持续返回。
-
如果函数式setState和setState混用,setState之前使用的函数式会被清空。
-
高阶函数表示接受一个函数为参数的函数。
// 类似于这种
fun()(succee)
// 它的操作内容类似于
function fun(){
... //
succee()
}
-
web实现实时的通信websocket
const websocket = new WebSocket("xxx"); // 创建实例
回调
websocket.onerror // 用于指定连接失败后的回调函数
WebSocket.onopen //用于指定连接成功后的回调函数
websocket.onmessage //接收到消息的回调方法
websocket.onclose //连接关闭的回调方法
方法
WebSocket.close() 关闭当前链接
WebSocket.send(data) 向服务器发送数据
在页面关闭前断开连接,防止页面报错。同理在组建销毁后也应该关闭websocket
window.onbeforeunload = function () {
closeWebSocket();
}
105
max-content是css3新属性。它代表内容的宽度不会让dom换行或被挤压。可以配合使用
width:max-content
over-flow:auto
106
在使用伪元素的时候必须书写content属性
p::after{
content:""
}
107
setTimeout在设置会返回一个专属的定时器id,setInterval也是同理。
var timeoutID = setTimeout(function[, delay]);
-
行内元素属性和文字是一致的。
-
vue 组件中凡事写明event事件的都是@触发的。所有非常量的变量都为单项绑定。
-
快速删除node包
rimraf node_modules
-
css3 新属性 calc为一个计算属性如
p{
width:calc(100%-100px);
}
此属性兼容性差,在特定尺寸的电脑会出问题。慎用。
-
xxx.toFixed()
保留几位浮点数。
113
Array.sort() 数组的排序,函数有a,b。小于 0 ,那么 a 会被排列到 b 之前。等于 0 , a 和 b 的相对位置不变。大于 0 , b 会被排列到 a 之前。
var arr= [];
arr.sort((a,b)=>a-b)
-
map
与 forEach
map
是返回新数组不能直接返回匿名对象(变成undefined),一定会返回数组。
forEach
类似于for...in实在数组循环中的操作。
-
text-align: justify;
适用于需要文字两端对齐。
-
在设立遮罩层的时候用这种写法
117
在微信端所有大的边距都用vw和vh。在ios10 的版本中不支持fixed元素的flex布局,做兼容处理。
-
element 的select组件在数据较多的时候会很卡,应用搜索加异步的方式。
-
element某些组件原始值应为【】,注意设置初始值的问题。
-
vue里面的watch默认是不监测对象(数组)的子元素的变化的,如果想就要使用深度监测如监测c
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
},
注意如果是数组的子元素发生改变时watch的val和oldval是一样的。而且官方并不认为是一个问题
https://github.com/vuejs/vue/issues/8668
121
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
reduce()函数的四个参数
Accumulator (acc) (累计器)
Current Value (cur) (当前值)
Current Index (idx) (当前索引)
Source Array (src) (源数组)
累加计算demo
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
sku组合demo
function calcDescartes (array) {
if (array.length < 2) return array[0] || [];
return array.reduce(function (col, set) {
var res = [];
col.forEach(function (c) {
set.forEach(function (s) {
var t = [].concat(Array.isArray(c) ? c : [c]);
t.push(s);
res.push(t);
})
});
return res;
});
}
console.log(calcDescartes([[1,2,3],['a','b','c'],['e','f']]))
122
element-ui form验证
-
Vue-route页面跳转时
this.$router.push()
使用query传值会出现在url里面
this.$router.push({path:'',query:""})
使用params传值必须传name
this.$router.push({name:'',params:""})
获取参数的时候
this.$route.params
124
-
Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in
循环遍历该对象时返回的顺序一致
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']
// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
126
不要给数组不存在的索引赋值,在循环的时候出现问题。
-
finally是try catch表示无论是否出错都会执行
try {
const data = await this.$axios.$get(`marketing/buying/${this.id}/ticketList`, {
params: {
...this.filter,
page
}
})
if (data.code === 'SUCCESS') {
this.data = data.lists
}
} catch (error) {
console.log(error)
} finally {
this.loading = false
}
128
PORT=3001 yarn dev 自定义端口启动,前提是nginx已经监听的此端口。
-
直接复制对象是浅拷贝,在对变量赋值vuex里面的数据时,开启严格模式下会报错。使用JSON.parse(JSON.stringify(object))是最简单快速的方法。
-
es6最快去重方法
let set = new Set([1,2,3,3,4,5,5,1,2,0]);
console.log([..set]);
-
Element-ui 中时间选择组件中的值不能为null或undefined,否则内部报错不在有双向绑定效果。