@jingwentian
2016-11-16T06:11:06.000000Z
字数 5189
阅读 1509
开发相关
名称 | 平台 | 简介 |
---|---|---|
Vagrant | Linux | 开发环境 |
SwitchHosts | Mac/Win | hosts 切换 |
前后端合作的主要目的,就是把后端产生的数据渲染到前端的模板中
前端的模板交给后端处理,直接写到后端逻辑中,或者通过 MVC 框架整合成后端的相对独立的部分;
后端的数据通过 API 的方式交给前端处理,通过 Ajax 等方式传输数据(或二者结合)。
如何选择以上两种协作方式
如果前端页面主要做内容展示,需要后端处理的内容比较多,而前端逻辑简单时,建议采用后端 MVC。
如果前端页面的交互和数据处理较多,可以将逻辑放在前端,而后端只负责数据存取。
开发前端框架/组件(如 bootstrap),统一规范且快速成型。
以命名规范为主,避免不同样式文件之间错综复杂的样式覆盖与重置、便于复用和维护
id、class 命名,在避免冲突并描述清楚的前提下尽可能短
<!-- good -->
<div id="nav"></div>
<!-- bad -->
<div id="navigation"></div>
<!-- good -->
<p class="comment"></p>
<!-- bad -->
<p class="com"></p>
<!-- good -->
<span class="author"></span>
<!-- bad -->
<span class="red"></span>
表单相关的属性正确应用
//color、date、datetime、datetime-local、email、month、number、range、search、tel、time、url、week
<input type="number" name="quantity" min="1" max="5">
<input type="number" name="points" min="0" max="100" step="10" value="30">
<input class="e-input" type="number" pattern="[0-9]*" maxlength="11" placeholder="请输入手机号" name="mobile" autofocus>
正确且有语义的层级嵌套
<div class="e-list-news e-list-news-default" >
<!--列表标题-->
<div class="e-list-news-hd e-cf">
<a href="" class="">
<h2>推荐酒店</h2>
<span class="e-list-news-more e-fr">更多 »</span>
</a>
</div>
<!--列表主体-->
<div class="e-list-news-bd">
<ul class="e-list">
<li class="e-g e-list-item-desced e-list-item-thumbed e-list-item-thumb-left">
<div class="e-u-sm-4 e-list-thumb">
<a href="" class="">
<img src="http://img.evente.cn/1.jpg" alt=""/>
</a>
</div>
<div class="e-u-sm-8 e-list-main">
<h3 class="e-list-item-hd"><a href="http://h.evente.cn/100000" class="">长隆酒店</a></h3>
<div class="e-list-item-text">长隆酒店简介</div>
</div>
</li>
</ul>
</div>
</div>
模块内部的类名需要继承自父级
/* 这是某个模块 */
.e-nav {}
.e-nav-title {}
.e-nav-li {}
.e-nav-li-active {}
.e-nav-li-disabled {}
模块状态: {命名空间}-{模块名}-{状态描述}
子模块: {命名空间}-{模块名}-{子模块名}
缩进(使用 4 个空格做为一个缩进层级)
// bad
$(".screen nav.screen-l li a").on("click", function() {
// code ....
});
$(".zezao").on("click", function() {
// code ....
})
// good
$(document.body).on('click', .screen nav.screen-l li', navbarSelect)
.on('click', '.zezao', hideLayer);
function navbarSelect(e) {
e.preventDefault();
// code ....
}
function hideLayer() {
// code ....
}
我们的目标是优先显示与用户要在网页上执行的主要操作有关的内容。
优化循环
for (var i = 0; i < data.length; i++) {
//do someting
}
for(var i = 0, m = data.length; i < m; i++) {
//do someting
}
或:
var i = data.length;
while(i--) {
//do someting
}
做好缓存
// bad
$('#top').find('p.classA');
$('#top').find('p.classB');
//good 选中某一个网页元素,是开销很大的步骤
var $top = $('#top');
$top.find('p.classA');
$top.find('p.classB');
使用链式操作
// jQuery自动缓存每一步的结果,因此比非链式写法要快
$('div').find('h3').eq(2).html('Hello');
节流的应用(延时请求、延时执行)
<div id="watch-example">
<p>Ask a yes/no question:<input v-model="question"></p>
<p>{{ answer }}</p>
</div>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 question 发生改变,这个函数就会运行
question: function (newQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.getAnswer()
}
},
methods: {
getAnswer: _.debounce(
function () {
var vm = this
if (this.question.indexOf('?') === -1) {
vm.answer = 'Questions usually contain a question mark. ;-)'
return
}
vm.answer = 'Thinking...'
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
},
500
)
}
})
</script>
onload 和 onerror回调函数的应用
// 静态文件加载失败后的切换
function _cdnFallback(org){
var nodeName = org.nodeName.toLowerCase()
, elem = document.createElement(nodeName)
, map = {script: 'src', link: 'href'}
, srcName = map[nodeName]
, src = org[srcName];
src = src.replace('https://static.evente.cn', 'https://static-bak.evente.cn');
if(nodeName == 'link'){
elem.rel = 'stylesheet';
}
elem[srcName] = src;
document.body.appendChild(elem);
}
<link href="https://static.evente.cn/evente/b/desktop/css/common/common.css" rel="stylesheet" onerror="_cdnFallback(this)" />
// 业务中的应用
<input type="file" onchange="dbImport()" />
function dbImport() {
var file = document.getElementById('file-import').files[0];
if(file) {
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = dbLoaded;
reader.onerror = errorHandler;
}
}
function dbLoaded(evt) {
// so sth
}
function errorHandler(evt) {
alertify.error('load error');
}
js 的一些小技巧
// 使用!!操作符转换布尔值
var money = 0;
console.log(!!money); //false
// 使用+将字符串转换成数字
function toNumber(strNumber) {
return +strNumber;
}
console.log(toNumber("1234")); // 1234
// 并条件符
conected && login();
// 等同于
if (conected) {
login();
}
// 使用||运算符
function User(name, age) {
this.name = name || "jingwentian";
this.age = age || 27;
}
// try catch
try {
a = null
a.name = 'jing'
} catch(err) {
console.error(err);
console.log(err.message); // Cannot set property 'name' of null
}
<link rel="dns-prefetch" href="http://img.evente.cn" />
文件按需加载
if (/MicroMessenger/i.test(navigator.userAgent)) document.write('<\/script>');
前端构建工具
前端模块管理器
css预处理器