文件名称统一用小写的英文字母、数字和下划线的组合,其中不得包含汉字、空格和特殊字符;命名原则的指导思想一是使得你自己和工作组的每一个成员能够方便的理解每一个文件的意义,二是当我们在文件夹中使用“按名称排例”的命令时,同一种大类的文件能够排列在一起,以便我们查找、修改、替换、计算负载量等等操作
图片的名称分为头尾两部分,用下划线隔开,头部分表示此图片的大类性质,尾部分表示此图片的名称
banner_sohu.png
banner_sina.png
// 反例
├── cn //存放中文HTML文件
├── en //存放中文HTML文件
├── images //存放图片文件
├── media //存放多媒体文件
├── css //存放样式文件
├── js //存放JavaScript脚本
└── ...
尽量确保文档和模板只包含 HTML 结构,样式都放到样式表里,行为都放到脚本里
建议统一两个空格缩进(总之缩进统一即可),不要使用 Tab 或者 Tab、空格混搭。
为每个 HTML 页面的第一行添加标准模式(standard mode)的声明, 这样能够确保在每个浏览器中拥有一致的表现。
<!DOCTYPE html>
在 HTML中指定编码 <meta charset="utf-8"> ;
<meta charset="utf-8">
优先使用最新版本的IE 和 Chrome 内核
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="keywords" content="关键词">
<meta name="description" content="描述">
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon">
强烈建议使用语义化标签
语义化的 HTML 结构,有助于机器(搜索引擎)理解,另一方面多人协作时,能迅速了解开发者意图。
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Style Guide</title>
<meta name="description" content="不超过150个字符">
<meta name="keywords" content="">
<meta name="author" content="name, email@gmail.com">
<!-- 为移动设备添加 viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="path/to/favicon.ico">
<!-- iOS 图标 -->
<link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png">
</head>
</html>
<div>这是正例</div>
<DIV>这是反例</DIV>
闭合标签/双标签(closing tag)需闭合
<div>这是正例</div>
<div>这是反例
自闭合/单标签(self-closing)无需闭合
<inpupt value="这是正例"/>
<inpupt value="这是反例"></input>
自定义属性规定以(data-*)形式出现
<div data-id="自定义属性值">自定义属性</div>
a连接的title(鼠标移入a显示的文字)
img标签的alt(图片连接错误显示的文字)
严格嵌套约束在所有的浏览器下都不被允许;而语义嵌套约束,浏览器大多会容错处理,生成的文档树可能相互不太一样。
语义嵌套约束
严格嵌套约束
HTML5 规范中 disabled、checked、selected 等属性不用设置值。
<inpupt tyle="text" disabled />
<inpupt tyle="checkbox" checked />
<select>
<option value="1" selected></option>
</select>
<!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 --><html lang="zh-cmn-Hans"> <!-- 更加标准的 lang 属性写法 http://zhi.hu/XyIa --><head>
<!-- 声明文档使用的字符编码 -->
<meta charset='utf-8'>
<!-- 优先使用 IE 最新版本和 Chrome -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<!-- 页面描述 -->
<meta name="description" content="不超过150个字符"/>
<!-- 页面关键词 -->
<meta name="keywords" content=""/>
<!-- 网页作者 -->
<meta name="author" content="name, email@gmail.com"/>
<!-- 搜索引擎抓取 -->
<meta name="robots" content="index,follow"/>
<!-- 为移动设备添加 viewport -->
<meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no">
<!-- `width=device-width` 会导致 iPhone 5 添加到主屏后以 WebApp 全屏模式打开页面时出现黑边 http://bigc.at/ios-webapp-viewport-meta.orz -->
<!-- iOS 设备 begin -->
<meta name="apple-mobile-web-app-title" content="标题">
<!-- 添加到主屏后的标题(iOS 6 新增) -->
<meta name="apple-mobile-web-app-capable" content="yes"/>
<!-- 是否启用 WebApp 全屏模式,删除苹果默认的工具栏和菜单栏 -->
<meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL">
<!-- 添加智能 App 广告条 Smart App Banner(iOS 6+ Safari) -->
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<!-- 设置苹果工具栏颜色 -->
<meta name="format-detection" content="telphone=no, email=no"/>
<!-- 忽略页面中的数字识别为电话,忽略email识别 -->
<!-- 启用360浏览器的极速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 不让百度转码 -->
<meta http-equiv="Cache-Control" content="no-siteapp" />
<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微软的老式浏览器 -->
<meta name="MobileOptimized" content="320">
<!-- uc强制竖屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ强制竖屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC强制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC应用模式 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<!-- windows phone 点击无高光 -->
<meta name="msapplication-tap-highlight" content="no">
<!-- iOS 图标 begin -->
<link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png"/>
<!-- iPhone 和 iTouch,默认 57x57 像素,必须有 -->
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/apple-touch-icon-114x114-precomposed.png"/>
<!-- Retina iPhone 和 Retina iTouch,114x114 像素,可以没有,但推荐有 -->
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144x144-precomposed.png"/>
<!-- Retina iPad,144x144 像素,可以没有,但推荐有 -->
<!-- iOS 图标 end -->
<!-- iOS 启动画面 begin -->
<link rel="apple-touch-startup-image" sizes="768x1004" href="/splash-screen-768x1004.png"/>
<!-- iPad 竖屏 768 x 1004(标准分辨率) -->
<link rel="apple-touch-startup-image" sizes="1536x2008" href="/splash-screen-1536x2008.png"/>
<!-- iPad 竖屏 1536x2008(Retina) -->
<link rel="apple-touch-startup-image" sizes="1024x748" href="/Default-Portrait-1024x748.png"/>
<!-- iPad 横屏 1024x748(标准分辨率) -->
<link rel="apple-touch-startup-image" sizes="2048x1496" href="/splash-screen-2048x1496.png"/>
<!-- iPad 横屏 2048x1496(Retina) -->
<link rel="apple-touch-startup-image" href="/splash-screen-320x480.png"/>
<!-- iPhone/iPod Touch 竖屏 320x480 (标准分辨率) -->
<link rel="apple-touch-startup-image" sizes="640x960" href="/splash-screen-640x960.png"/>
<!-- iPhone/iPod Touch 竖屏 640x960 (Retina) -->
<link rel="apple-touch-startup-image" sizes="640x1136" href="/splash-screen-640x1136.png"/>
<!-- iPhone 5/iPod Touch 5 竖屏 640x1136 (Retina) -->
<!-- iOS 启动画面 end -->
<!-- iOS 设备 end -->
<meta name="msapplication-TileColor" content="#000"/>
<!-- Windows 8 磁贴颜色 -->
<meta name="msapplication-TileImage" content="icon.png"/>
<!-- Windows 8 磁贴图标 -->
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml"/>
<!-- 添加 RSS 订阅 -->
<link rel="shortcut icon" type="image/ico" href="/favicon.ico"/>
<!-- 添加 favicon icon -->
<!-- sns 社交标签 begin -->
<!-- 参考微博API -->
<meta property="og:type" content="类型" />
<meta property="og:url" content="URL地址" />
<meta property="og:title" content="标题" />
<meta property="og:image" content="图片" />
<meta property="og:description" content="描述" />
<!-- sns 社交标签 end -->
<title>标题</title></head>
注意:
名称 | 文件名 |
---|---|
主要的 | master.css |
模块 | module.css |
基本共用 | base.css |
布局,版面 | layout.css |
主题 | themes.css |
专栏 | columns.css |
文字 | font.css |
表单 | forms.css |
补丁 | mend.css |
打印 | print.css |
/**
**
@description: 中文说明
@author: 作者
@update: 2013-04-13 18:32
**
**/
/* mischieff 2019-7-17 */
注意事项:
.lz-class{} /* 乐佐助简写 lz */
.mis-class{} /* mischieff本人简写 */
.lz-class{}
.lz-login{
opsition:absolute;
top:0;
left:0;
border: 1px solid red;
font-size: 16px;
}
/*
样式渲染时,由于定位(position)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在首位。
盒模型决定了组件的尺寸和位置,因此排在第二位。其他属性只是影响组件的内部(inside)或者是不影响前两组属性,因此排在后面。
*/
/*url() 、属性选择符、属性值使用双引号。*/
.lz-login{
background: url("http://ss.bdimg.com/static/superlanding/img/logo_top.png");
}
.lz-login{
font: 12px/1.5 serif;
padding: 0 10px;10
}
.lz-login{
margin: 0;
padding: 0;
}
为了防止文件合并及编码转换时造成问题,建议将样式中文字体名字改成对应的英文名字,如:
黑体(SimHei)
宋体(SimSun)
微软雅黑 (Microsoft Yahei,几个单词中间有空格组成的必须加引号)
直接使用"font+字体大小"作为名称,如下所示:
.font12px {
font-size: 12px;
}
.font9pt {
font-size: 9pt;
}
为了页面性能考虑,如果浏览器不支持CSS3相关属性的,则该浏览器的某些特效将不再支持,属性的支持情况如下表所示(Y为支持,N为不支持)
浏览器 | 圆角 | 阴影 | 动画 | 文字阴影 | 透明 | 背景渐变 | 空间变换 |
---|---|---|---|---|---|---|---|
Chrome 5+ | Y | Y | Y | Y | Y | Y | Y |
Firefox 4+ | Y | Y | Y | Y | Y | Y | Y |
Safari 5+ | Y | Y | Y | Y | Y | Y | Y |
Opera | Y | Y | Y | Y | Y | N | Y |
Ie 9+ | Y | Y | N | N | Y | N | Y |
Chrome 5- | N | N | Y | Y | Y | Y | Y |
Safari 5- | N | Y | Y | Y | Y | N | Y |
Ie 8 | N | N | N | N | N | N | N |
Ie 7 | N | N | N | N | N | N | N |
Ie 6 | N | N | N | N | N | N | N |
font-family 属性中的字体族名称应使用字体的英文 Family Name,其中如有空格,须放置在引号中;常见的字体族名称如下
西文字体在前,中文字体在后
body{
font-family: Arial, "Microsoft YaHei", sans-serif;
}
字体 | 操作系统 | Family Name |
---|---|---|
宋体 (中易宋体) | Windows | SimSun |
黑体 (中易黑体) | Windows | SimHei |
微软雅黑 | Windows | Microsoft YaHei |
微软正黑 | Windows | Microsoft JhengHei |
华文黑体 | Mac/iOS | STHeiti |
冬青黑体 | Mac/iOS | Hiragino Sans GB |
容器: container
页头:header
内容:content/container
页面主体:main
页尾:footer
导航:nav
侧栏:sidebar
栏目:column
页面外围:wrapper
左右中:left right center
导航:nav
主导航:mainbav
子导航:subnav
顶导航:topnav
边导航:sidebar
左导航:leftsidebar
右导航:rightsidebar
菜单:menu
子菜单:submenu
标题: title
摘要: summary
标志:logo
广告:banner
登陆:login
登录条:loginbar
注册:regsiter
搜索:search
功能区:shop
标题:title
加入:joinus
状态:status
按钮:btn
滚动:scroll
标签页:tab
文章列表:list
提示信息:msg
当前的: current
小技巧:tips
图标: icon
注释:note
指南:guild
服务:service
热点:hot
新闻:news
下载:download
投票:vote
合作伙伴:partner
友情链接:link
版权:copyright
/**
* @param {Grid} grid 需要合并的Grid
* @autho mischieff 2015/07/21
**/
注释名 | 含义 | 语法 | 示例 |
---|---|---|---|
@param | 描述参数的信息 | @param 参数名 {参数类型} 描述信息 | @param name {String} 传入名称 |
@return | 描述返回值的信息 | @return {返回类型} 描述信息 | @return {Boolean} true:可执行;false:不可执行 |
@autho | 描述此函数作者的信息 | @author 作者信息 [附属信息:如邮箱、日期] | @author 张三 2015/07/21 |
@version | 描述此函数的版本号 | @version XX.XX.XX | @version 1.0.3 |
建议不再使用 var,而使用 let / const,优先使用 const。任何一个变量的使用都要提前申明,除了 function 定义的函数可以随便放在任何位置。
var _myStyle = {}
var my_Style = {}
function stringFormat(theBells){}
function Student(name) {
this.name = name;
}
var st = new Student('tom');
动词 | 含义 | 返回值 |
---|---|---|
can | 判断是否可执行某个动作 ( 权限 ) | 函数返回一个布尔值true:可执行;false:不可执行 |
has | 判断是否含有某个值 | 函数返回一个布尔值。true:含有此值;false:不含有此值 |
is | 判断是否为某个值 | 函数返回一个布尔值。true:为某个值;false:不为某个值 |
get | 获取某个值 | 函数返回一个非布尔值 |
set | 设置某个值 | 无返回值、返回是否设置成功或者返回链式对象 |
//是否为可读
function canRead(){
return true;
}
下面的布尔表达式都返回 false:
但小心下面的, 可都返回 true:
建议不再使用双引号,静态字符串使用单引号,动态字符串使用反引号衔接。
// 反例
const foo = "后除"
const bar = foo + ",前端工程师"
// 正例
const foo = '后除'
const bar = `${foo},前端工程师`
匿名函数统一使用箭头函数,多个参数/返回值时优先使用对象的结构赋值。
// 反例
function getPersonInfo (name, sex) {
return [name, gender]
}
// 正例
function getPersonInfo ({name, sex}) {
return {name, gender}
}
函数名统一使用驼峰命名,以大写字母开头申明的都是构造函数,使用小写字母开头的都是普通函数,也不该使用 new 操作符去操作普通函数。
建议使用扩展运算符(...foo)拷贝对象而不是 Object.assign(target, ...sources)。
// 错误
const foo = {a: 0, b: 1}
const bar = Object.assign(foo, {c: 2})
// 正例
const foo = {a: 0, b: 1}
const bar = {...foo, c: 2}
统一使用 import / export 的方式管理项目的模块
// lib.js
export default {}
// app.js
import app from './lib'
import 统一放在文件顶部。
操作符始终写在前一行, 以免分号的隐式插入产生预想不到的问题。
for (var i = 0; i < arr.length; i++) {}
这样的方式遍历不是很好
,尤其当 arr 是 Dom 对象的时候,这样就会一直在访问 Dom 层,访问 Dom 层的代价是很大的。
for (var i = 0, j=arr.length; i < j; i++) {}
这样的方式去用循环是比较好
的,只会访问一次 Dom 层(不适用于 Dom 节点会动态更新的场景)。
(1)数组的解构赋值
//最基本的写法
{
let a,b
[a,b] = [1,2]
console.log(a,b) // 1,2
}
// 加默认值
{
let a,b
[a,b,c=3] = [1,2]
console.log(a,b,c) // 1,2,3
}
// 使用场景// 1. 变量的值交换
{
let a = 1
let b = 2
[a,b] = [b,a]
console.log(a,b) //2, 1
}
// 2. 从函数的返回值取值
{
function f(){
return [1,2]
}
let a,b
[a,b] = f()
console.log(a,b) // 1, 2
}
// 3. 从函数的返回值中取值,并且弄成我们想要的格式
{
function f(){
return [1,2,3,4,5]
}
let a,b,c
[a,,,b]=f()
console.log(a,b) //1,4
}
// 4. 同样,取我们想要的
{
function f(){
return [1,2,3,4,5]
}
let a,b,c
[a,...b]=f()
console.log(a,b) //1, [2,3,4,5]
}
// 5. 取我们想要的,意思就是乐意要啥就拿啥
{
let a,b,rest
[a,b,..rest] = [1,2,3,4,5]
console.log(a,b,rest) // 1, 2, [3,4,5]
}
(2)对象的解构赋值
// 基本写法
{
let a,b
{{a,b} = {a:1,b:2}}
console.log(a,b) // 1, 2
}
{
let o = {a:1,q:true}
let {a,p} = o
console.log(a,q) //1,true
}
// 加默认值
{
let {a=10,b=1} = {a=1}
console.log(a,b) //1,1 ,默认值会被后面的值替换
}
// 使用场景// 模拟后端接口,取我们想要的值
{
let data = {
title: 'a',
test:[{
title: 'b'
desc: 'desc'
}]
}
let {title:esTitle,test:[{title:cTitle}]} = data
console.log(esTitle,cTitle) // a ,b
}
(1)遍历接口
// es5
let str='\u{20bb7}abc'
for(let i =0;i<str.length;i++){
console.log(str[i]) // 乱码 乱码 a b c
}
// es6
for(let code of str){
console.log(code) // 𠮷 a b c for of 可以正确识别
}
(2)新的常用方法
// includes startsWith endsWith
{
let str = 'string'
console.log(str.includes('r')) // true
console.log(str.startsWith('s')) // true
console.log(str.endsWith('g')) // true
}
//复制 repeat
{
let str = 'abc'
console.log(str.repeat(2)) // abcabc
}
//忽略换行
{
console.log(String.raw`Hi\n${1+2}`) Hi\n3
console.log(S`Hi\n${1+2}`) // 换行
}
// padStart padEnd 这两个还处于草案阶段,要使用babel-polyfill进行编译
{
console.log('1',padStart(2.'0')) //01 第一个参数是长度,长度不够补0
console.log('1',padEnd(2.'0')) //10
}
(3)模板字符串
{
let name="dou";
let info="hello";
let m=`i am ${name},${info}`;
console.log(m); //i am dou, hello
}
(1)新增方法,常用的
{
// 检查是不是有限的 (-2^53,2^53)
console.log(Number.isFinite(1)) // true
console.log(Number.isFinite(NaN)) // false
console.log(Number.isFinite(1/0)) // false
// 检查是不是NaN
console.log(Number.isNaN(NaN)) // true
console.log(Number.isNaN(0)) // false
}
{
// 检查是不是整数
console.log(Number.isInteger(1)) //true
// 这要注意
console.log(Number.isInteger(1.0)) //true
console.log(Number.isInteger(1.1)) //false
console.log(Number.isInteger('1')) //false
}
{
// 最大和最小安全数值
console.log(Number.MAX_SAFE_INTEGER)
console.log(Number.MIN_SAFE_INTEGER)
console.log(Number.isSafeIntger(1)) //true
}
{
// 取整
console.log(Math.trunc(1.1)) //1
console.log(Math.trunc(1.9)) //1
//判断一个数到底是正数、负数、还是零
console.log(Math.sign(-2)) //-1
console.log(Math.sign(0)) // 0
console.log(Math.sign(2)) // 1
console.log(Math.sign('2')) // 1
console.log(Math.sign('aa')) // NaN
}
(2)新增方法,新特性
{
// Array.of 将一组值,转换为数组
let arr = Array.of(1,2,3,4)
console.log(arr) [1,2,3,4]
let emptyArr = Array.of()
console.log(emptyArr) // []
//Array.from 把类数组转为数组
console.log(Array.from([1,2,3],function(item){
return item*2 // 2,4,6
}))
//fill填充 第二个和第三个参数,用于指定填充的起始位置和结束位置
console.log([1,'a',undefined].fill(1)) //[1,1,1]
console.log([a,b,c],fill(7,1,3)) // [a,7,7]
}
// key values entries
{
for(let i of [1,2,3].key()){
console.log(i) //0,1,2
}
//兼容
for(let v of [1,2,3].values()){
console.log(v) //1,2,3
}
for(let [i,v] of [1,2,3].entries()){
console.log(i,v) // 0 1 1 2 2 3
}
}
//copyWithin将指定位置的成员复制到其他位置,并返回新数组
{
console.log([1,2,3,4,5].copyWithin(0,3,4)) //[4,2,3,4,5]
}
//find findIndex 找出第一个符合条件的数组成员
{
console.log([1,2,3,4,5,6].find(function(item){
return item>3
})) // 4 只找一次
console.log([1,2,3,4,5,6].findIndex(function(item){
return item>3
})) // 3 只找一次
}
// includes 找数组里的值,可以找NaN
{
console.log([1,2,NaN].includes(1)) //true
console.log([1,2,NaN].includes(NaN)) //true
}
// 函数参数的默认值
{
function test(x, y = 'world'){
console.log('默认值',x,y);
}
test('hello'); // hello world
// 如果传的参数默认值会被替换
test('hello','dou'); //hello dou
// 注意这会带来一个作用域的问题
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
// 设置默认值,会形成一个单独的作用域等到初始化结束,这个作用域就会消失
let x = 1;
function f(y = x) {
let x = 2;
console.log(y);
}
f() // 1
}
// rest参数
{
function test3(...arg){
for(let v of arg){
console.log('rest',v);
}
}
test3(1,2,3,4,'a') //1,2,3,4,a
// rest参数会将传入的字符串转化为数组
}
//扩展运算符 相当于rest的逆运算=>把数组展开
{
console.log(...[1,2,4]); // 1,2,4
console.log('a',...[1,2,4]); // a,1,2,4
}
// 箭头函数 不在说了
{
let arrow = v => v*2;
console.log(arrow(1)) // 2
}
// 尾调用,优化用,不再展开,基本形式如下
{
function tail(x){
console.log('tail',x);
}
function fx(x){
return tail(x)
}
fx(123) // tail 123
}
{
// 简洁表示法
let o=1;
let k=2;
let es5={
o:o,
k:k
};
let es6={
o,
k
};
console.log(es5,es6); // 是一样的结果
let es5_method={
hello:function(){
console.log('hello');
}
};
let es6_method={
hello(){
console.log('hello');
}
};
console.log(es5_method.hello(),es6_method.hello()); // 也是一样的,在vue中我们就是用的简洁表示
}
{
// 属性表达式
let a='b';
let es5_obj={
a:'c',
b:'c'
};
let es6_obj={
[a]:'c'
}
console.log(es5_obj,es6_obj) // es5的就不说了 es6输出 {b:c}
}
{
// is
console.log(Object.is('abc','abc'),'abc'==='abc') // true true
console.log(Object.is([],[]),[]===[]); // false false
// 注意
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
//assign
console.log('拷贝',Object.assign({a:'a'},{b:'b'})) // {a:a,b:b} 注意这是浅拷贝
// entries
let test={k:123,o:456};
for(let [key,value] of Object.entries(test)){
console.log([key,value])
// [k,123] [o,456]
}
}
{
// 扩展运算符
let {a,b,...c}={a:'test',b:'kill',c:'ddd',d:'ccc'};
// babel对这个支持还不是很友好
c={
c:'ddd',
d:'ccc'
}
}
(1)Set
// 声明方式1
{
let list = new Set()
list.add(5)
list.add(7)
console.log(list.size) // 2
}
// 声明方式2
{
let arr = [1,2,3,4,5]
let list = new Set(arr)
console.log(list.size) // 5
}
// 不可以有重复的成员
{
let list = new Set()
list.add(1)
list.add(2)
list.add(1)
console.log(list); // 只有 1,2// 用途 数组去重
let arr=[1,2,3,1,2]
let list2=new Set(arr)
console.log(list2) // 1,2,3
}
// api crud 不再多说 看栗子
{
let arr=['add','delete','clear','has']
let list=new Set(arr)
console.log('has',list.has('add')) // true
console.log('delete',list.delete('add'),list) // 'delete','clear','has'
list.clear() // 没了都删了
console.log('list',list)
}
// 遍历 都是我们常用的
{
let arr=['add','delete','clear','has']
let list=new Set(arr)
for(let key of list.keys()){
console.log('keys',key)
}
for(let value of list.values()){
console.log('value',value)
}
for(let [key,value] of list.entries()){
console.log('entries',key,value)
}
list.forEach(function(item){console.log(item)})
}
// weakSet 这玩意成员只能是对象,Set有的方法他都有
{
let weakList=new WeakSet()
let arg={}
weakList.add(arg)
console.log(weakList);
}
(2)Map
// 声明方式
// map的key可以是任意数据类型
{
let map = new Map()
let arr=['123']
map.set(arr,456)
console.log('map',map,map.get(arr)) // 456
}
// 常用api,和set很类似,放控制台打印就明白
{
let map = new Map([['a',123],['b',456]])
console.log('map',map)
console.log('size',map.size)
console.log('delete',map.delete('a'),map)
console.log('clear',map.clear(),map)
}
// weakmap 和weakSet一样 成员必须是对象
{
let weakmap=new WeakMap()
let o={}
weakmap.set(o,123)
console.log(weakmap.get(o))
}
(3)Set,Map和数组,对象的横向对比
{
// map和array的对比
// 数据结构横向对比,增,查,改,删
let map=new Map()
let array=[]
// 增
map.set('t',1)
array.push({t:1})
console.info('map-array',map,array)
// 查
let map_exist=map.has('t');
let array_exist=array.find(item=>item.t)
console.info('map-array',map_exist,array_exist)
// 改
map.set('t',2)
array.forEach(item=>item.t?item.t=2:'')
console.info('map-array-modify',map,array)
// 删
map.delete('t')
let index=array.findIndex(item=>item.t)
array.splice(index,1)
console.info('map-array-empty',map,array)
}
{
// set和array的对比
let set=new Set()
let array=[]
// 增
set.add({t:1})
array.push({t:1})
console.info('set-array',set,array)
// 查
let set_exist=set.has({t:1})
let array_exist=array.find(item=>item.t)
console.info('set-array',set_exist,array_exist)
// 改
set.forEach(item=>item.t?item.t=2:'')
array.forEach(item=>item.t?item.t=2:'')
console.info('set-array-modify',set,array)
// 删
set.forEach(item=>item.t?set.delete(item):'')
let index=array.findIndex(item=>item.t)
array.splice(index,1)
console.info('set-array-empty',set,array)
}
{
// map,set,object对比
let item={t:1}
let map=new Map()
let set=new Set()
let obj={}
// 增
map.set('t',1)
set.add(item)
obj['t']=1
console.info('map-set-obj',obj,map,set)
// 查
console.info({
map_exist:map.has('t'),
set_exist:set.has(item),
obj_exist:'t' in obj
})
// 改
map.set('t',2)
item.t=2
obj['t']=2
console.info('map-set-obj-modify',obj,map,set)
// 删除
map.delete('t')
set.delete(item)
delete obj['t']
console.info('map-set-obj-empty',obj,map,set)
}
组件名为多个单词,并且用连接线(-)连接,避免与 HTML 标签冲突,并且结构更加清晰。
<page-header></page-header>
(1)组件的名字应该始终是以连接线(-)连接的单词,一方面可与组件名一致,使项目更加清晰,另一方面这样的写法对编辑器引入也很友好。
// 反例
├── index.html
├── main.js
└── components
└── pageheader
// 正例
├── index.html
├── main.js
└── components
└── page-header //此处为(-)连接
(2)对于例如按钮、下拉框或表格这样的基础组件应该始终以一个特定的前缀开头,区别与其他业务
组件
// 反例
├── index.html
├── main.js
└── components
├── page-header
├── page-article
├── page-header
├── mazey-button
├── mazey-select
└── mazey-table
// 正例
├── index.html
├── main.js
└── components
| ├── page-header
| ├── page-article
| └── page-header
└── base
├── mazey-button
├── mazey-select
└── mazey-table
定义 Prop 的时候应该始终以驼峰格式命名
*,在父组件赋值的时候使用连接线(-)。这里遵循每个语言的特性,因为在 HTML 标记中对大小写是不敏感的,使用连接线更加友好;而在 JavaScript 中更自然的是驼峰命名。
// 反例
props: {
article-status: Boolean
}
//HTML
<article-item :articleStatus="true"></article-item>
// 正例
props: {
articleStatus: Boolean
}
//HTML
<article-item :article-status="true"></article-item>
Prop 的定义应该尽量详细的指定其类型、默认值和验证。
// 反例
props: ['attrM', 'attrA']
// 正例
props: {
attrM: Number,
attrA: {
type: String,
required: true
},
attrZ: {
type: Object,
default: function () { // 数组/对象的默认值应该由一个工厂函数返回
return {
msg: '成就你我'
}
}
}
}
v-for 遍历的时候,总是应该带上 key 值使更新 DOM 时渲染效率更高。
<li v-for="item in list" :key="item.id">
{{ item.title }}
</li>
若同一组 v-if 逻辑控制中的元素逻辑相同,Vue 为了更高效的元素切换,会复用相同的部分,例如:value。为了避免复用带来的不合理效果,应该在同种元素上加上 key 做标识。
// 反例
<div v-if="hasData">
<span>{{ mazeyData }}</span>
</div>
<div v-else>
<span>无数据</span>
</div>
// 正例
<div v-if="hasData" key="mazey-data">
<span>{{ mazeyData }}</span>
</div>
<div v-else key="mazey-none">
<span>无数据</span>
</div>
为了统一规范始终使用指令缩写,使用v-bind,v-on并没有什么不好,这里仅为了统一规范
<input :value="userName" @click="userName">
为了避免样式冲突,整个项目要么全都使用 scoped 特性,要么使用 BEM 约定。
// 反例
<style>
/* CSS */
</style>
<script>
/* JavaScript */
</script>
<template>
<!-- HTML -->
</template>
// 正例
<template>
<!-- HTML -->
</template>
<script>
/* JavaScript */
</script>
<style>
/* CSS */
</style>
名称 | 命名方法 | 词汇种类 | 说明 | 举例 |
---|---|---|---|---|
局部变量名 | Camel命名法 | 名词 | fristName | |
全局变量名 | Camel命名法 | 名词 | 前缀:g | gFristName |
参数名 | Camel命名法 | 名词 | fristName | |
方法/属性 | Camel命名法 | 名词 | fristName | |
私有(保护)成员 | Camel命名法 | 名词 | 前缀:_ | _fristName |
常量名 | 名词 | 下划线+全体大写 | ADD_METHOD | |
类名 | Pascal命名法 | 名词 | AtiveDic | |
Bool类型 | Camel命名法 | 名词 | 前缀:is/has | hasChild |
动词 | 含义 | 举例 |
---|---|---|
Can | 判断是否可以执行某个权限 | CanLogin |
Has | 判断是否含有某个值 | HasToken |
Is | 判断是否为某个值 | IsShowModel |
Get | 获取某个值 | GetUserId |
Set | 设置某个值 | SetCookie |
Load | 加载某些数据 | LoadList |
Update | 更新某些数据 | UpdateUserInfo |
Del | 删除某些数据 | DelMenu |
定义:大多数组件在定义时就可以通过各种自定义参数来实现组件的定制。
编程注意事项:
//正例
const { name } = this.porps;
console.log(name);
//反例
console.log(this.props.name);
定义:State是一个组件的UI数据模型,是组件渲染时的数据依据。
编程注意事项:
//正例
this.setState({name:'Lucy'});
//反例
this.state.name = 'Lucy';
//正例
this.setState((prevState, props) => ({
name: prevState.name + props.increment
}));
//反例
this.setState({name:this.state.name});
尽可能减少代码中的注释。可以通过让变量名更语义化、只注释复杂、潜在逻辑,来减少注释量,同时也提高了可维护性,毕竟不用总在代码与注释之间同步了。
//正例
render(){
return(
<div>
...
<UserInfo />
...
</div>
);
}
//反例
render(){
return(
<div>
...
<UserInfo></UserInfo>
...
</div>
);
}
//正例
<Foo hidden={true}/>
//反例
<Foo hidden />
//正例
{todos.map(todo => (
<Todo {...todo} key={todo.id} />
))}
//反例
{todos.map((todo, index) =>
<Todo{...todo} key={index} />
)}
//正例
<Foo ref={(ref) => { this.myRef = ref; }} />
//反例
<Foo ref="myRef"/>
在render中只进行页面的渲染,不作对数据或者逻辑的处理
// 反例
const splitLocale = locale.split('‑');
const language = splitLocale[0];
const country = splitLocale[1];
// 正例
const [language, country] = locale.split('‑');
对所有定义的或者传入的变量,都进行默认设置或者判定是否为undefined,防止数据未定义时程序报错。
// 反例
onChange(value => console.log(value.name))
// 反例
onChange((value) => {
if (!value) {
value = {}
}
console.log(value.name)
})
// 正例
onChange((value = {}) => console.log(value.name))
// 正例
onChange(value => console.log(value?.name))
不要信任任何回调函数给你的变量,它们随时可能是 undefined ,使用初始值是个不错的选择,但有的时候初始值没什么意 义,使用?.
语法可以安全的访问属性
//反例
let newslist = this.props.newslist;
let b = a // a为数组
//正例
let { newslist = [] } = this.props;
let b = a || [];