vuejs基础

整   理:肖雅君

时   间:2016-11-18

说   明:vue.js的安装、基本用法

官网:http://vuejs.org.cn/

1.安装
安装npm,建议安装cnpm,超超快速。
淘宝镜像:npm install -g cnpm --registry=https://registry.npm.taobao.org
安装vue:npm install -g vue-cli【cnpm install -g vue-cli】

2.初始化:
vue init webpack vueTest
[项目类型]-如:使用webpack这个模板,进行压缩和打包

依次输入:项目名
项目描述
项目开发者
是否使用语法检测工具
是否进行单元测试
是否进行集成测试

3.下载依赖:cnpm install
下载完毕后,打开项目,一般所需修改的页面文件在src文件夹下,打开package.json文件,能看到我们在初始化项目的时候,输入的项目名、开发者等信息,如下图:
6

其中src文件夹下有个component文件夹,是专门安置自己封装的组件,引用这些组件的时候,直接在src文件夹下app.vue中引入,如下图:
7

4.在项目文件夹下运行项目:npm run dev
注:需要npm的版本在3.0.0,否则error。
升级npm:npm -g install nom@3.0.0 [用npm依旧是等待很长时间没反应,用cnpm很快]
1
升级完成后运行,浏览器自动跳转到8080端口打开测试页:
2

5.项目的页面是src文件下的 app.vue,修改这个文件夹即可。
另,后缀是.vue文件,在用brackets 或者sublime软件编辑的时候,需要安装对应的插件,才可显示高亮。
brackets vue插件:http://brackets.dnbard.com/extension/brackets.vue
sublime vue 插件: Vue Syntax highlight/Jade

6.重要指令:
new 一个vue对象时,可以设置:
(1)对象的属性:
数据:data
方法:method
监听:watch
new Vue()对象,注意大小写。new vue()无效。
(2)关联:
模板html页面和vue对象的粘合,用模板指令v-text、v-html进行数据渲染
(3)控制显示和隐藏:v-if、v-show
v-if通过控制dom结构控制显隐。v-show:控制css样式的display来控制显隐。
(4)循环渲染:v-for
(5)事件绑定:v-on
<button v-on:click = "doThis"></button>
简写:
<button @click = "doThis"></button>
(6)属性绑定:v-bind
<img v-bind:src="imageSrc" :class="{ red: isRed }"/>

7.基本功能和应用:
(1)数据的双向绑定
(2)v-show和v-if的使用
(3)事件处理
(4)组件化方法
(5)代码逻辑或者业务逻辑的输出处理:computed
(6)列表输出
(7)组件化综合应用:列表输出 + 组件化结合
(8)添加任务总数和删除任务
(9)jquery 、ajax 和vue的结合
(10)vue-resource插件的使用

8.代码demo
(1)数据的双向绑定

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://vuejs.org.cn/js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>{{myhead}}</h1>
    <h1 v-text="mytext"></h1>
    <input type="text" v-model="mytext" />
    <!--打印出data里的代码,测试双向绑定过程-->
    <pre>
            {{$data | json}}
    </pre>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            myhead:'你好!',
            mytext:'My name is Michellya!'
        }
    });
</script>
</body>
</html>

(2)v-show和v-if的使用

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://vuejs.org.cn/js/vue.js"></script>
<style>
        p{color:#f00;}
</style>
</head>
<body>
<div id="app">
    <h1>{{myhead}}</h1>
    <h1 v-text="mytext"></h1>
    <p v-if="!mytext">警告:请填写内容!</p>
    <input type="text" v-model="mytext" />
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            myhead:'你好!',
            mytext:''
        }
    });
</script>
</body>
</html>

(3)事件处理

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://vuejs.org.cn/js/vue.js"></script>
<style>
        p{color:#f00;}
</style>
</head>
<body>
<div id="app">
    <button @click="mysubmit">submit</button>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            myhead:'你好!',
            mytext:''
        },
        methods:{
            mysubmit:function(){
                alert(11);
            }
        }
    });
</script>
</body>
</html>

(4)组件化

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://vuejs.org.cn/js/vue.js"></script>
<style>
        p{color:#f00;}
</style>
</head>
<body>
<div id="app">
<!--组件化:1.自己定义组件-->
    <mylabel mychoice="赞" bgcolor="red"></mylabel>
    <mylabel mychoice="嘘" bgcolor="blue"></mylabel>

<!--2.用h5的新标签template  组件封装——应用1:类似微博的喜欢、不喜欢的点选计数-->
    <template id="choice-model">
        <h3>{{mychoice}}</h3>
        <button @click="num += 1" style="background:{{bgcolor}}">{{num}}</button>
    </template>        
</div>

<script>
    Vue.component('mylabel',{
        template: '#choice-model',
        props:['mychoice','bgcolor'],
        data:function(){
            return {num : 0}
        }
    });

    new Vue({
        el: '#app',
    });
</script>
</body>
</html>

(5)代码逻辑或业务逻辑的输出处理:computed

应用1:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://vuejs.org.cn/js/vue.js"></script>
<style>
        p{color:#f00;}
</style>
</head>
<body>
<div id="app">
<!--        level {{level <= 100 ? '普通会员' : 'VIP会员'}}  -->

    level {{level}}
</div>

<script>
/*
    new Vue({
        el: '#app',
        data: {
            points: 200,
            level: '普通会员'
        }
    });
*/
    new Vue({
        el: '#app',
        data: {
            points: 200,
        },
        computed:{
            level:function(){
                if(this.points <= 100){
                        return '普通会员';
                }
                return 'VIP会员';
            }
        }
    });
</script>
</body>
</html>

应用2:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://vuejs.org.cn/js/vue.js"></script>
<style>
        p{color:#f00;}
</style>
</head>
<body>
<div id="app">
    用户名:{{username}}
    <br/>
    <input type="text" v-model="first" />
    <input type="text" v-model="second" />
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            first: 'Michelle',
            second: 'yajun',
        },
        computed:{
            username:function(){
                return this.first + ' ' + this.second;
            }
        }
    });
</script>
</body>
</html>

(6)循环列表输出

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://vuejs.org.cn/js/vue.js"></script>
<style>
    p{color:#f00;}
    .mydone{text-decoration:line-through;}
    .nodone{color:coral;}
</style>
</head>
<body>
<div id="app">
    <ul>
<!--                <li :class="task.completed ? 'mydone' : '' " v-for="task in tasks">{{task.body}}</li>-->
        <li :class="{'mydone':task.completed,'nodone':!task.completed }" 
                v-for="task in tasks"
                @click = "toggleclick(task)">{{task.body}}</li>
    </ul>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            tasks:[
                 {body:'sleeping',completed:false},
                 {body:'shopping',completed:true},
                 {body:'swimming',completed:true},
                 {body:'running',completed:false},
            ]
        },
                methods:{
            toggleclick:function(task){
                task.completed = !task.completed;
            }
        }
    });
</script>
</body>
</html>

(7)组件化list综合应用:todo应用

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://vuejs.org.cn/js/vue.js"></script>
<style>
    p{color:#f00;}
    .mydone{text-decoration:line-through;}
    .nodone{color:coral;}
</style>
</head>
<body>
<div id="app">
    <mytask :list="tasks"></mytask>
    <mytask :list="[{body:'唱歌',completed:true},{body:'跳舞',completed:false},]"></mytask>
    <mytask :list="tasks"></mytask>

<!--组件化:将每日任务变成组件list-->
<template id="mytask-model">
    <ul>
        <li :class="{'mydone':task.completed,'nodone':!task.completed }" 
                v-for="task in list"
                @click = "toggleclick(task)">{{task.body}}</li>
    </ul>
</template>
</div>

<script>
Vue.component('mytask',{
        template: '#mytask-model',
        props: ['list'],
        methods: {
            toggleclick:function(task){
                task.completed = !task.completed;
            }
        }
    });

    new Vue({
        el: '#app',
        data: {
            tasks:[
                {body:'sleeping',completed:false},
                {body:'shopping',completed:true},
                {body:'swimming',completed:true},
                {body:'running',completed:false}
            ]
        }
    });
</script>
</body>
</html>

(8)添加任务总数、删除任务和添加任务

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://vuejs.org.cn/js/vue.js"></script>
<style>
    p{color:#f00;}
    .mydone{text-decoration:line-through;}
    .nodone{color:coral;}
</style>
</head>
<body>
<div id="app">     
    <mytask :list="tasks"></mytask>

<!--组件化:将每日任务变成组件list-->
<template id="mytask-model">
    <h1>My Task <span v-show="remaining">({{ remaining}})</span></h1>
    <ul>
        <li :class="{'mydone':task.completed,'nodone':!task.completed }" 
                v-for="task in list"
                @click = "toggleclick(task)">{{task.body}}
                <strong @click="deleteTask(task)">点我删除</strong>        
        </li>        
    </ul>
</template>
</div>

<script>
    Vue.component('mytask',{
        template: '#mytask-model',
        props: ['list'],
        methods: {
            toggleclick:function(task){
                task.completed = !task.completed;
            },
            deleteTask:function(task){
                this.list.$remove(task);
            }
        },
        computed:{
            remaining:function(){
                return this.list.filter(function(task){
                    return ! task.completed;
                }).length;
            }
        }
    });

    new Vue({
        el: '#app',
        data: {
            tasks:[
                {body:'sleeping',completed:false},
                {body:'shopping',completed:true},
                {body:'swimming',completed:true},
                {body:'running',completed:false}
            ]
        }
    });
</script>
</body>
</html>

(9)jquery 、ajax 和vue的结合
3

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<style>
    p{color:#f00;}
    .mydone{text-decoration:line-through;}
    .nodone{color:coral;}
</style>
</head>
<body>
<div id="app">
        
    <mytask>{{ $task }}</mytask>

<!--组件化:将每日任务变成组件list-->
<template id="mytask-model">
    <h1>My Task <span v-show="remaining">({{ remaining}})</span></h1>
    <ul>
        <li :class="{'mydone':task.completed,'nodone':!task.completed }" 
                v-for="task in list"
                @click = "toggleclick(task)">@{{task.body}}
                <strong @click="deleteTask(task)">点我删除</strong>        
        </li>        
    </ul>
</template>
</div>
<script src="http://vuejs.org.cn/js/vue.js"></script>
<script src="http://file2.ci123.com/ast/js/jquery_172.js"></script>
<script>
    Vue.component('mytask',{
        template: '#mytask-model',
        //创建一个空list数组
        data:function(){
            return {
                list:[]
            }
        },
        methods: {
            toggleclick:function(task){
                task.completed = !task.completed;
            },
            deleteTask:function(task){
                this.list.$remove(task);
            }
        },
        computed:{
            remaining:function(){
                return this.list.filter(function(task){
                    return ! task.completed;
                }).length;
            }
        },
        create:function(){
           $.getJSON('api/...',function(data){
                this.list = data; 
            })
        }
    });

    new Vue({
        el: '#app'
    }
});
</script>
</body>
</html>

(10)vue-resource插件的使用

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue js - Michellya</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<style>
    p{color:#f00;}
    .mydone{text-decoration:line-through;}
    .nodone{color:coral;}
</style>
</head>
<body>
<div id="app">
        
    <mytask></mytask>

<!--组件化:将每日任务变成组件list-->
<template id="mytask-model">
    <h1>My Task <span v-show="remaining">({{ remaining}})</span></h1>
    <ul>
        <li :class="{'mydone':task.completed,'nodone':!task.completed }" 
                v-for="task in list"
                @click = "toggleclick(task)">@{{task.body}}
                <strong @click="deleteTask(task)">点我删除</strong>        
        </li>        
    </ul>
</template>
</div>

<script src="http://vuejs.org.cn/js/vue.js"></script>
<script src="https://github.com/vuejs/vue-resource"></script>

<script>
    Vue.component('mytask',{
        template: '#mytask-model',
        data:function(){
            return {
                list:[]
            }
        },
        methods: {
            toggleclick:function(task){
                task.completed = !task.completed;
            },
            deleteTask:function(task){
                this.list.$remove(task);
            }
        },
        computed:{
            remaining:function(){
                return this.list.filter(function(task){
                        return ! task.completed;
                }).length;
            }
        },
        create:function(){
            this.$http.get('api/...',function(){

            })
        }
    });

    new Vue({
        el: '#app',
    });
</script>
</body>
</html>

9.强荐浏览器插件:vue-devtools
作用、操作及下载:http://www.cnplugins.com/devtool/vuejs-devtools/
插件:
4
界面:
5

Javascript中的this的全面解析

——《你不知道的Javascript(上卷)》总结

整   理:肖雅君

时   间:2016-10-21

说   明:Javascript中的this的全面解析

this关键字的js最复杂的机制,是一个很特别的关键字,被自动定义在所有的函数作用域中,但是实际使用的时候很难说出this到底指向什么。下面将分2部分介绍this,每一部分都有各自解析的重点和主要内容。

一、this的含义和误区
1.为什么使用this
2.两种常见的对this的误解
3.this到底是什么

二、this的深入解析
1.什么是调用位置
2.绑定规则
(1)默认绑定
(2)隐式绑定
(3)显式绑定
(4)new绑定
3.this词法

【this的含义和误区】

一、为什么使用this
书中通过两段代码的对比来解释为什么要使用this,第一段代码如下:这段代码在不同的上下文对象(you和me)中重复使用函数identify()和speak(),不用针对不同的对象编写不同版本的函数:
function identify(){
return this.name.toUpperCase();
}
function speak(){
var greeting = "Hello, I am" + " " +identify.call(this);
console.log(greeting);
}
var me = {name:"Jay"};
var you = {name:"reader"};

identify.call(me);//JAY
identify.call(you);//READER
speak.call(me);//Hello, I am JAY
speak.call(you);//Hello, I am READER

如果不使用this,那就需要给identify()和speak()显示传入一个上下文对象:

function identify(cxt){
return cxt.name.toUpperCase();
}
function speak(cxt){
var greeting = "Hello, I am" + " " +identify(cxt);
console.log(greeting);
}
var me = {name:"Jay2"};
var you = {name:"reader2"};

identify(you);//READER2
speak(me);//Hello, I am JAY2

对比发现:this提供了一种更好的方式在隐式“传递”一个对象引用。因为随着模式越来越复杂,显式传递上下文对象会让代码变得越来越混乱。因此,通过使用this可以将API设计的冯家简洁,并且易于复用。

二、两种常见的对于this的误解

1-误解1:指向函数本身

把this理解成指向函数本身,这种推断是按照英语语法的角度来推断的。
常见的在函数内部引用自身的情况有:递归或者是一个在第一次被调用后自己解除绑定的事件处理器。新手会认为:既然可以把函数看作一个对象,那就可以在调用函数时存储状态(属性的值)。
下面来通过记录分析函数foo被调用的次数来证明下this并不是指向的函数本身:

function foo(num){
console.log("foo:" + num);
this.count++;//记录foo被调用的次数
}
foo.count = 0;
for(var i = 0; i < 10; i++){
if(i>5){
foo(i);
}
}
//foo:6
//foo:7
//foo:8
//foo:9
console.log(foo.count); //0

为什么会是0呢?
foo()函数中的console.log语句产生了4条输出,证明foo()确实被调用了4次,但是foo.count仍然是0,所以,从字面上理解,this指向函数本身是错的。那么,问题的原因是什么呢?
foo()函数是在全局作用域下执行的,this在这段代码中其实指向window,并这段代码再无意中创建了一个全局变量count,他的值是NaN。
那么为什么ths的行为和预期的不一致呢?书中提供了三种解决方法,其中前两种方法,回避了this的含义和工作原理。代码如下:

方法一:运用作用域(词法作用域)方法,该方法解决了我们遇到的问题,但是没有直面this.

function foo(num){
console.log("foo" + num);
data.count++;//记录foo被调用的次数
}
var data = {count:0};

for (var i = 0; i < 10; i++){
if(i > 5){
foo(i);
}
}
//foo6
//foo7
//foo8
//foo9
console.log(data.count);//4

===========================拓展分界线===========================

补充:这边涉及到一个作用域的问题,js中所说的词法作用域其实就是静态作用域,我随便扒了一段代码,来解释下js里的词法作用域和其他语言的作用域的区别。

比如说,在c#中有一段代码:
static void Main(string[] args)
{
if(true)
{
int num = 10;
}
Console.Write(num);
}
//报错: 因为上下文中不存在num这个变量。因为这边的作用域是用花括号决定的,叫做块级作用域。

换种方式:
static void Main(string[] args)
{
if(true)
{
int num = 10;
System.Console.WriteLine(num);
}
}
而在js中:
if(true) {
var num = 10;
}
alert(num);
//10

弹出框10,所以在js中变量的作用范围是怎么限定的呢?

1.函数限定变量作用域:
在JS中,只有函数可以限定一个变量的作用范围。
也就是说,在JS中,在函数里面定义的变量,可以在函数里面被访问,但是在函数外无法访问。看如下代码:
var func = function() {
var num = 10;
};
try{
alert(num);
}catch( e ){
alert( e );
};
//抛出异常:num is not defined

这段代码再执行的时候,会抛出异常:num is not defined;因为num是在函数里面定义的,在函数外则不能使用。也就是说,在函数里面定义的变量在函数外不能使用,在函数内可随意使用,即使是在赋值之前。如下代码:(注:调试的时候在浏览器控制台调试不会抛出异常,会正常弹出10,需在本地测试。)

var func = function(){
alert(num);
var num = 10;
alert(num);
};
try{
func();
}catch(e){
alert(e);
}
这段代码运行后,不会抛出错误,会产生两次弹窗,一次undefined一次10(下文解释为什么,这里面涉及到“变量名提升和函数名提升”的概念)。从这里可以看出,变量只有在函数中可以被访问,同理在改函数中的函数也可以访问。

2.子域访问父域
之前说了,函数可以限定变量的作用域,那么在函数中的函数就可以成为该作用已的子域。在子域中的代码可以访问到父域中的变量,代码如下:
var func = function(){
var num = 10;
var sub_func = function(){
alert(num);
};
sub_func();
};
func();//10
这段代码的执行结果是10,可看出子欲可访问父域中的变量num。但是子域中访问父域的代码也是有条件的,如下:

var func = function(){
var num = 10;
var sub_func = function(){
var num = 20;
alert(num);
}
sub_func();
}
func();//20
执行结果是20,此时的num输出的是子域里的值。

由此可见js中的变量访问规律:js解释器现在当前的作用域中搜索是否有该变量的定义,如果有,则使用这个变量;如果无,则到父级中去寻找。层层往上,直到顶级作用域,如果顶级中也不存在,则抛出异常“变量未定义”。
综合如下:
(function() {
var num = 10;
(function() {
var num = 20;
(function(){
alert(num);
})()
})();
})();

//这段代码执行后打印出20. 如果将"var num = 20;"去掉,那么打印的就是10. 同样,如果再去掉"var num = 10",那么就会出现未定义的错误。

3.变量名提升和函数名提升
变量名提升:
var num = 10;
var func = function() {
alert(num);
var num = 20;
alert(num);
};
func();
//undefined 20

像这样将代码定义在后面,而在前面使用的情况在Js中很常见,如:
var num = 10;
var func = function(){
var num;// 感觉就是这里已经定义了,但是没有赋值一样
alert(num);
var num = 20;
alert(num);
};
func();
这种现象就被称为变量名提升。

同样有函数名提升:
var func = function() {
alert("调用外面的函数");
};

var foo = function() {
func();
var func = function() {
alert("调用内部的函数");
};
func();
};

===========================拓展分界线END===========================

方法二 :创建一个指向函数对象的词法标识符(变量)来引用它。同样该方法仍旧回避了this的问题。
function foo(num){
console.log("foo: " + num);
foo.count++; // foo指向它自身
}
foo.count = 0;
for(var i=0; i<10; i++){
if(i > 5){
foo(i);
}
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9
console.log(foo.count);// 4

方法三: 因为this在foo函数执行时指向了别处,所以可强制this指向foo函数。
function foo(num){
console.log("foo: " + num);
this.count++;
}
foo.count = 0;
for(var i=0; i<10; i++){
if(i > 5){
foo.call(foo, i); //使用call()可以确保this指向函数本身
}
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9
console.log(foo.count);// 4

2-误解2:指向函数作用域

第二种常见的误解是:this指向函数作用域。这个问题有点复杂,因为在某种情况下它是正确的,但在其他情况下他却是错误的。
但一定要明白,this在任何情况下都不指向函数的作用域,在javascript内部作用域和对象确实很相似,可见的标识符都是他的属性,但作用域“对象”无法通过JavaScript代码访问,它存在于JavaScript引擎内部。
function foo(){
var a = 2;
this.bar();
}
function bar(){
console.log(this.a);
}
foo();
// undefined
这段代码试图通过this联通foo()和bar()的词法作用域,从而让bar()可以访问foo()作用域的变量a。这是错误的。

三、this到底是个什么鬼
排除以上的几种误解,可以得出以下结论:
1.this是在运行时进行绑定的,并不是在编写的时候绑定的。
2.this的绑定和函数的声明的位置没有关系,只取决于函数的调用方式。

具体细节是:当一个函数被调用的时候,会创建一个活动记录,这个活动记录会包含一些信息,如:函数在哪里被调用、函数的调用方式、传入的参数等等,而this就算这个记录的一个属性,会在函数执行的时候被用到。

四、总结
1.随着程序使用的模式越来越复杂,显示传递上下文对象会让代码显得很乱,因此通过this隐式传递可以将API设计的更加简洁并且利于复用。
2.this既不指向函数自身,也不指向函数的作用域。
3.this实际上是函数被调用时发生的绑定,它的指向完全取决于函数在哪里被调用。

关于变量的作用域的小结:
在js中词法作用域又叫做静态作用域,作用域的访问规则可以画成一个作用域链:
1) 作用域链就是对象的数组
2) 全部script是0级链,每个对象占一个位置
3) 凡是看到函数延伸一个链出来,一级级展开
4) 访问首先看当前函数,如果没有定义往上一级链检查
5) 如此往复,直到0级链

【this的深入解析】

调用位置
调用位置:就是函数在代码中被调用的位置(而不是声明位置)。要想回答htis到底引用的什么,只有仔细分析调用位置才能回答这个问题。
而分析条用位置最重要的就是分析调用栈。
调用栈:就是为了到达当前执行位置所调用的所有的函数。
function baz(){
//当前调用栈是:baz
//因此,当前调用位置是全局作用域
console.log("baz");
bar();//bar的调用位置
}
function bar(){
//当前的调用栈是:baz -> bar
//因此,当前的调用位置是在baz中
console.log("bar");
foo();//foo的调用位置
}
function foo(){
//当前的调用栈是baz -> bar -> foo
//因此,当前的调用位置是在baz中
console.log("foo");
}
baz();//baz的调用位置

绑定规则
思路:通过找到函数的调用位置,然后判断需要应用规则中的哪一条,便可决定this的绑定对象。关于this的绑定规则主要有一下四种:
(1)默认绑定
(2)隐式绑定
(3)显式绑定
(4)new绑定

1.默认绑定
默认绑定的典型类型是:独立函数调用。如下代码:
function foo(){
console.log(this.a);
}
var a = 2;
foo();//2
调用foo()函数的时候,函数应用了默认绑定,this指向全局对象window(这是在非严格模式下,若是在严格模式下会报错),所以this.a被解析成了全局变量a。所以,可在不使用任何修饰的函数引用进行调用,只能使用默认绑定,无法应用其他规则。

2.隐式绑定
隐式绑定的常见形式上在调用位置具有上下文对象,或者说被某个对象拥有或者包含。如下:
function foo(){
console.log(this.a);
}
var obj = {a:2, foo:foo};

obj.foo(); //2
这里的函数是foo()是预先定义好的,然后将其添加为obj对象的引用属性。调用位置使用obj上下文对象来引用函数,因此可以说函数被调用的时候obj对象“拥有”或者“包含”它。无论你怎么称呼这种模式,当foo()被调用时,它的前面确实加上了obj的引用,当函数引用上下文对象时,隐式绑定规则就会把函数调用中的this绑定到这个上下文对象。所以,this.a和obj.a是一样的。

另一个需要注意的点是:对象属性引用链中只有最后一层或者说最顶层会影响调用位置。
function foo(){
console.log(this.a);
}
var obj1 = {a:1, obj2:obj2};
var obj2 = {a:100, foo:foo};
obj1.obj2.foo();//100

隐式丢失
隐式绑定最常见的问题就是隐式丢失 -> 隐式绑定的函数会丢失绑定对象。也就是说它会应用“默认绑定”,而把this绑定到全局对象或者undefined上,取决于是否是严格模式。【*1】
function foo(){
console.log(this.a);
}
var obj = {a:2, foo:foo}

var bar = obj.foo;//函数别名
var a = "global";//a是全局对象的属性
bar();//"global"

虽然bar是obj.foo的一个引用,但实际上,他引用的是foo函数本身,因此,此时的bar()其实是一个不带任何修饰的函数调用,因此,它应用了“默认绑定”。

===========================拓展分界线===========================
*1-备注:js中函数调用的两种方法:
function test(a){
alert("你输入的是:" + a);
}

//方法一:直接调用
test("臣妾做不到啊!");

//方法二:函数赋值给变量
var mytst = test;
mytst("贱人就是矫情");//用变量来调用函数

===========================拓展分界线END===========================

一种更微妙、更常见的并且更出乎意料的情况发生在传入回调函数时:
function foo(){
console.log(this.a);
}
function callBack(fn){
//fn其实引用的是foo
fn();//调用位置
}
var obj = {a:2, foo:foo}
var a = "global";
callBack(obj.foo);//"global"

参数传递其实就是一种隐式赋值,这句话可以用下面的两段代码来详细的讲解:
(1)代码一
var a = 1;
function fn(){
alert(a);
a = 2;
}
fn();
alert(a);
(2)代码二
var a = 1;
function fn(a){
alert(a);
a = 2;
}
fn();
alert(a);

在第一段代码中:
首先,在全局作用域中,先通过变量提升,找到了标识符a和函数fn,a此时有个默认的undefined。然后,在执行阶段,程序先将变量a赋值为1,紧接着执行函数fn(),此时在函数域中,依旧应用变量提升的规则,但是什么都没有找到,紧接着执行函数内的代码alert(a),因为在函数中并没有找到变量a。所以,通过作用域链向上层的父级作用域中查找,我们找到了a,并且此时a的值已经被赋值为1,所以alert(a)的结果是1。下一句:a = 2,注意,a前面没有关键字var ,即:这里的a是全局的,也就说在执行a =2 时,它修改的是全局作用域中a 的值,所以alert(a)时,值自然为2。

在第二段代码中:
同样通过变量提升,找到标识符a和函数fn,a此时的默认值也是undefined。开始执行,a 先被赋值1,然后函数执行,这里与第一段代码的不同处在于,在函数fn中传入了参数a,那么这么做的结果就是:在函数域先运用变量提升的规则的时候,不会像第一段代码中那样,什么都找不到,而相当于定义了一个值为undefined(调用的时候没有传入参数)的变量a,所以执行函数中的alert(a)时,结果为undefined,而不会像第一种情况听过作用域链向上查找。因为本函数中已经找到了a,只不过是以参数的形式传入的。同理代码(a = 2)会修改a的值,即在函数域中,a的值现在为2(可以去尝试在函数中最后面alert一下a的值)。而在函数外执行alert(a),我们得到的结果便是1,因为该句代码是在全局中执行的,即会在全局中去查找变量a,而不会去访问函数域中的a。这也是因为,在JavaSceipt中子作用域可以访问父作用域而反过来却不行的规则。

回到this绑定丢失的话题上,上面讲这么多,其实就是想说明:参数传递其实就是一种隐式赋值,参数传递其实就是一种隐式赋值,参数传递其实就是一种隐式赋值。重要的事情三遍。
按照上面的方式来解析代码:在执行callBack(obj.foo)时,在函数作用域通过变量提升,找到了参数fn,它的默认值是undefined,然后将参数传入,其实相当于(var fn = obj.foo),这就是与前面的将其直接赋值给一个变量对等上了,然后再执行fn(),应用“默认绑定”,此时的this已经不指向obj了,而是指向window(严格模式)。

如果把函数传入内置的函数而不是传入自己声明的函数,会发生什么呢?
function foo(){
console.log(this.a);
}
var objg = {a:2, foo:foo};
var a = "global";

setTimeout(obj.foo, 1000);//"global"

结果还是一样的。
因为javascript环境中内置的setTimeout()函数实现和下面的伪代码类似:
function setTimeout(fn,dalay){
//等待delay秒
fn();//调用位置
}
回调函数丢失this绑定的情况是非常常见的,并且还有一种情况this的行为会出乎我们意料:调用回调函数的函数可能会修改this。由于无法控制回调函数的执行方式,因此就没有办法控制调用位置得到期望的绑定。

那么如何通过固定this来“修复”这个问题呢?
即:如何解决this的丢失问题。

显示绑定
在隐式绑定中,我们必须在一个对象的内部包含一个指向函数的属性,并通过这个属性间接引用函数,从而把this间接绑定到这个对象上。那么,如果我们不想在每个对象内部包含函数引用,而想在每个对象上强制调用函数,该怎么做呢?

这时就需要call(绑定this,其他参数...)和apply(绑定this,其他参数...) 这两个方法了。这两个方法的第一个参数都是给this准备的,不同之处在于其他参数的形式上,他们两的其他参数对比如下:
call(绑定this,"参数1","参数2","参数3","参数4");
apply(绑定this,["参数1","参数2","参数3","参数4"]);

===========================拓展分界线===========================
注:跑题之apply和call
apply的其他参数是以数组序列形式存在的,它会在执行时将其解析成单个的参数再依次的传递到调用的函数中,这有什么用处呢?加入我们有一个数组:
var arr = [1,2,3,4,5,6];
现在我要找到其中的最大值,当然这里有很多方法了。既然这里讲到apply那么我们就用apply方法来解决这个问题。如果想要找到一组数中最大的一个,有一个简单的方法,使用Math.max(...)。但是,该方法并不能找出一个数组中的最大值,也就是说:
Math.max(1,2,3,4,5); // 可以找到最大值5
Math.max([1,2,3,4,5]); // NAN这就不行了,因为不接受以数组作为参数

我们的做法就是通过:
Math.max.apply(null, [1,2,3,4,5]); //得到数组中的最大值5

===========================拓展分界线END===========================

通过call()和apply()这两种方法我们可以显式的绑定this到指定的对象:
function foo(){
console.log(this.a);
}
var obj = {a: 2}
foo.call(obj);//2

这两个方法是如何工作的呢? 它们的第一个参数是一个obj对象, 它们会把这个对象obj绑定到this,接着在调用函数foo时指定这个this。 因为你可以直接指定this 的绑定对象,也就是obj, 因此我们称之为显式绑定。也就是说:在调用 foo 时强制把它的 this 绑定到 obj 上

但是,显式绑定仍旧无法解决this丢失绑定的问题。

1.硬绑定
显式绑定的一个变种可以解决这个问题。
function foo(){
console.log(this.a);
}
var obj = {a: 2}
var bar = function(){
foo.call(obj);
}
bar();// 2

setTimeout(bar, 100); // 2

// 硬绑定的 bar 不可能再修改它的 this
bar.call(window); // 2

看看它是如何工作的:我们创建了一个函数bar(),并在他的内部手动调用foo.call(obj)。因此,强制把foo的this绑定到了obj,无论之后如何调用函数bar,它总会手动在obj上调用foo。这样的形式我们称之为硬绑定。

硬绑定的典型应用场景就是创建一个包裹函数,负责接收参数并返回值:
function foo(something){
console,log(this.a, something);
return this.a + something;
}
var obj = {a: 2}

var bar = function(){
return foo.apply(obj, arguments);
}
var b = bar(3); //2, 3
console.log(b); //5

硬绑定是一种非常常用的模式,所以ES5提供了内置的方法Function.prototype.bind,它的用法如下:
function foo(something){
console,log(this.a, something);
return this.a + something;
}
var obj = {
a:2
}
var bar = foo.bind(obj);
var b = bar(3); //2, 3
console.log(b); //5

bind(..) 会返回一个硬编码的新函数, 它会把参数设置为 this 的上下文并调用原始函数。

2. API调用的“上下文”
第三方库的许多函数, 以及 JavaScript 语言和宿主环境中许多新的内置函数, 都提供了一
个可选的参数, 通常被称为“ 上下文”( context), 其作用和 bind(..) 一样, 确保你的回调
函数使用指定的 this。
举例来说;
function foo(el){
console.log(el, this.id);
}
var obj = {id: "awesome"};
// 调用 foo(..)时把this绑定到obj
[1, 2, 3].forEach(foo, obj ); // 1 awesome 2 awesome 3 awesome

这些函数实际上就是通过 call(..) 或者 apply(..) 实现了显式绑定, 这样你可以少些一些代码。

new 绑定
第四条规则,也是最后一条规则,在讲解他之前我们首先要澄清一个非常常见的关于javascript中函数和对象的误解。在传统的面向类的语言中,“构造函数”是类中的一些特殊方法,使用new初始化类是会调用类中的构造函数。通常的形式是这样:
someThinges = new MyClass(...)
javascript中也有个new操作符,但javascript中的new操作符的机制与面向类的语言完全不同。

首先我们重新定义一下JavaScrit中的“构造函数”。
在Javascript中,构造函数只是一些使用new操作符时被调用的函数。它并不会属于某个类,也不会实例化一个类。实际上它甚至都不能说是一种特殊的函数类型,它们只是被new操作符调用的普通函数而已。

举例来说,思考一下Number()作为构造函数时的行为,ES5.1中这样描述它:

Number构造函数
当Number在new表达式中被调用时,它是一个构造函数:它会初始化新建的对象。
所以,包括内置对象函数在内的所有函数都可以用new来调用,这种函数被称为构造函数调用,这有个非常细微的区别:实际上并不存在所为的“构造函数”,只有对于函数的“构造调用”。使用new来调用函数,会自动执行下面的操作:
(1)创建一个全新的对象
(2)这个新对象会被执行[[原型]]连接(之后会细说)
(3)这个新对象会绑定到函数调用的this
(4)如果函数没有返回其他对象,那么new表达式中的函数会自动返回这个对象。

如下代码:
function foo(a){
this.a = a
}
var bar = new foo(2);
console.log(bar) // foo {a: 2}
console.log(bar.a); //2

使用new 来调用foo(...)时,我们会构造一个新的对象,并把它绑定到foo(...)调用中的this上。new是最后一种可以影响函数调用时this绑定行为的方法。我们称之为new绑定。

箭头函数
我们之前介绍的四条规则已经可以包含所有正常是有的函数。但是在ES6中介绍了一种无法使用这些规则的特殊函数类型:箭头函数
箭头函数不是使用function关键字定义的,而是使用“ => ”定义。箭头函数不使用this的四种标准规则,而是根据外层作用域(函数或全局)来决定this。

最终小结:
如果要判断一个运行中函数的this绑定,就需要找到这个函数的直接调用位置。找到后就可以顺序应用下面这四条规则来判断this的绑定对象:
判断this:
1. 函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象。
var bar = new foo()
2. 函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this 绑定的是指定的对象。
var bar = foo.call(obj2)
3. 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象。
var bar = obj1.foo()
4. 如果都不是的话, 使用默认绑定。 如果在严格模式下, 就绑定到 undefined, 否则绑定到全局对象。
var bar = foo()

另:ES6中的箭头函数不会使用四条标准的绑定规则,而是根据词法作用域来决定this,具体来说,箭头函数会继承外层函数调用的this绑定(无论this绑定到了什么),这其实和ES6之前代码中的self = this 机制一样。

微信UI开发样式库介绍

整    理:肖雅君

时    间:2016-03-25

说    明:WeUI是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页开发量身设计,可以令用户的使用感知更加统一。

一、微信web开发调试工具

1.介绍

2.下载安装

3.界面及功能

二、微信UI开发样式库

1.安装:npm install --save weui

2.元素类型

3.使用方法

3.1 简单的列表

3.2 单/复选列表框

3.3 开关

3.4 表单

3.5 选择框

 

一、微信web开发调试工具

1.介绍

当我们在用浏览器调试基于微信的网页的时候,经常遇到“请在微信打开的情况”,这使得前端在调试页面的时候非常不方便,微信推出了 web 开发者工具。它是一个桌面应用,通过模拟微信客户端的表现,使得开发者可以使用这个工具方便地在 PC 或者 Mac 上进行开发和调试工作。

2.下载安装

下载链接:https://mp.weixin.qq.com/wiki/10/e5f772f4521da17fa0d7304f68b97d7e.html#.E4.B8.8B.E8.BD.BD.E5.9C.B0.E5.9D.80

直接安装即可。

3.界面及功能

运行此开发工具,初始界面:

1

功能:

(1)可以使用自己的微信号来调试微信网页授权页面

(2)可以调试、检验页面的JS-SDK相关功能与权限,模拟部分SDK的输入和输出。

(3)可以使用基于weinre的移动调试功能

(4)可以利用集成的Chrome DevTools协助开发。

使用:

1.输入网址后会弹窗二维码,需手机微信确认后才能使用,如下图

24

3

2.输入网址,能打开页面,但是还是不能调试,需开发者和公众号绑定关系。5为了保证开发者身份信息的安全,对于希望调试的公众号,微信要求开发者微信号与公众号建立绑定关系。具体操作为:公众号登录管理后台,启用开发者中心,在开发者工具——web 开发者工具页面,向开发者微信号发送绑定邀请。

详情见链接:https://mp.weixin.qq.com/wiki/10/e5f772f4521da17fa0d7304f68b97d7e.html

二、微信UI样式库

WeUI是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页开发设计,可以使用户的使用感知更加统一。在微信网页开发中使用 WeUI,有如下优势:

同微信客户端一致的视觉效果,令所有微信用户都能更容易地使用你的网站
便捷获取快速使用,降低开发和设计成本
微信设计团队精心打造,清晰明确,简洁大方

1.安装:npm install --save weui

生成文件node_modules:里面包含weui文件夹,weui里有微信样式库使用的demo、样式文件和js文件。

67

 

使用的时候,直接引用weui里的样式文件即可,如下:

<link rel="stylesheet" href="node_modules/weui/dist/style/weui.min.css"/>

法2:无需安装,直接复制weui.css样式到自己的项目文件夹下。

2.元素类型

微信UI封装了几个常用的元素样式,

(1)Button按钮

(2)Cell列表视图

(3)Dialog弹窗

(4)Progess进度条

(5)Toast临时弹窗

(6)Msg page结果页

(7)Article文章段落

(8)Actionsheet可交互的动作集合

(9)Icon图标

3.使用方法

首先要熟悉微信UI类名的命名规律,每个类名上对应了各自的样式,有的父类结合子类代表某个样式。如下,以Cell列表视图作介绍。

一行列表weui_cell分成三个部分组成,类似于将一个表格分成三列,第一列weui_cell_hd、第二列 weui_cell_bd、第三列weui_cell_ft,可以将其理解成head,body,footer。另外,若是要采用自适应布局,需在需自适应的部分加上 class weui_cell_primary,如下图的“新闻”部分。

weui_cell_hd weui_cell_bd weui_cell_ft

3.1 简单的列表

        weui_cells_title:列表标题

         weui_cells:列表集(用来区分不同的列表,里面包含多个weui_cell

         weui_cells_access:跳转入口,结合weui_cell_ft使用(即小箭头,如需要入口箭头,则给weui_cells再添加类名weui_cells_access,并且必须有weui_cell_ft

         weui_cell:一个列表(一个列表里包含weui_cell_hdweui_cell_bdweui_cell_ft

图示:9

代码:列表

3.2 /复选列表框

         单选列表框:weui_cells_radio

         复选列表框:weui_cells_checkbox

          二者都采用隐方式结构(结合显方式)<label></label>[weui_check_label]里嵌套input[weui_check]span[weui_icon_checked]标签,span标签为选中时候的样式标签。

(1)单选

图示:17

代码:单选

(2)复选框

图示:18代码:多选

3.3 开关

         开关:weui_cell_switch

         开关按钮:input[weui_switch]

图示:11

代码:12

3.4 表单

          表单:[weui_cell_form]

         文字:weui_label(姓名)

         输入框:weui_input(请输入姓名号)

         验证码:weui_vcode

         错误报警:weui_cell_warn

         错误报警图标:<i class="weui_icon_warn"></i>

图示:13

代码:14

3.5 选择框

         选择:weui_cell_select

         情况一:箭头在前面weui_select_before结合weui_cell_hd使用

         情况二:箭头在后面weui_select_after结合weui_cell_bd使用

图示:16

代码:15

4.详细介绍

其他元素的使用方法在此不多赘述,微信公众平台开发者文档里结合图片和文字,介绍得非常清楚。

详情见链接:https://mp.weixin.qq.com/wiki/2/ae9782fb42e47ad79eb7b361c2149d16.html#Icon

结合demo:

http://weui.github.io/weui/

列表demo:weui

 

专题模块化改版

整    理:肖雅君

时    间:2016-03-04

说    明:专题模块化:手机端仍需前端切,PC端改用统一的模板,只需将切好的WAP端代码复制到模板里,再将css样式中的尺寸大小变成WAP端的2倍即可。(钱昱成正做成后台,后续会更新此文档。)

一、新专题步骤

1.<!doctype html>前

2.<head></head>

3.<body></body>

二、新老专题比较

1、顶部php

2、头部

3、头部以及右侧分享部分

4、右侧栏部分

5、评论模块不变

6、公共底部

 

一、新专题步骤

  1. <!doctype html>

<?php

include_once('../include/global.php');

$special_id = 10379;

$share_title = '产后抑郁,产后抑郁症,产后抑郁如何治疗.。。。 ';//分享的标题[修改]

$share_content = '新生命的降生.。。。';//分享内容[修改]

$share_pic = 'http://www.ci123.com/special/survey-yiyu/styles/images/share_pic.jpg';//分享的图片[修改]

include_once('../global/new_special/info.php');

if(isMobile()){

header("Location:http://m.ci123.com/special/survey-yiyu");//手机端专题链接[修改]

die();

}

?>

<!doctype html>

<html>

</html>

2.<head></head>

<head>

<meta charset="utf-8">

<title>惊!九成产妇有产后抑郁倾向?!</title>//专题标题[修改]

<meta name="renderer" content="webkit">

<meta http-equiv="X-UA-Compatible" content="IE=Edge">

<?php include_once('../global/new_special/share.php');?>

<link rel="stylesheet" href="styles/style_sub.css">//主要内容的样式[修改]

</head>

3.<body></body>

<body>

<?php include_once("../global/header.php");?><!--育网公共头部php-->

<div class="wrapper-special">

<div class="special-content">

<!--专题头部-->

<div class="part-content part-header">

<?php include_once('../global/new_special/part1.php');?><!--专题头部php-->

</div>

<!--专题头部-END-->

<!--右侧栏-->

<div class="part-content">

<?php include_once('../global/new_special/part2.php');?><!--右侧栏[“往期回顾+更多推荐”]php-->

</div>

<!--右侧栏-END-->

<!--左侧主体内容 -->

<div class="part-main">

<!-- 此处放主体内容 \ 此处放主体内容 \ 此处放主体内容-->

<!--左侧主体内容-END-->

</div>

</div>

</div><!—整体页面-->

<!--底部版权-->

<?php include_once('../global/new_special/footer.php');?>

<!--底部版权end-->

<div style="display:none;"><script src="http://s11.cnzz.com/stat.php?id=1257703690&web_id=1257703690" language="javascript"></script></div>//统计代码[修改]

</body>

 

二、新老专题比较

1、顶部php

原版:1-2

新版:1-3

改变内容:

(1)替换掉原来的帖子id(现在从库里取,需从后边编辑帖子那边添加)

(2)分享文案只需在开头添加

(3)需引入include_once('../global/new_special/info.php');(必须在$special_id后面引入)

2、头部

原版:1-2

新版:1-4

3、头部以及右侧分享部分

3

代码:<?php include_once('../global/new_special/part1.php');?>

4、右侧栏部分

4

代码:<?php include_once('../global/new_special/part2.php');?>

5、评论模块不变

5

引入此段代码:<?php include_once('../global/reply.php');?>

6、公共底部

6

代码:<?php include_once('../global/new_special/footer.php');?>

 

【前端技术文档】gulp spriter 插件使用

整    理:肖雅君

时    间:2016-02-05

说    明:gulp-css-spriter 将css代码中的切片图片合并成雪碧图

一、下载安装gulp

1.1 下载安装node.js

1.2 命令行测试是否安装成功

1.3 定位到项目

1.4 安装gulp

二、开始使用gulp

2.1 新建gulpfile.js文件

三、gulp-css-spriter

3.1 gulp-css-spriter使用步骤

3.2  使用技巧

一、下载安装gulp

1.1 下载安装node.js

下载链接:https://nodejs.org/en/   下载后直接安装即可。

1.2 命令行测试是否安装成功

Cmd

输入命令:Node –v  看是否返回node版本号,若是返回则安装成功。

输入命令:npm –v  同上是否返回npm的版本号

如下图:则是安装成功。

1

Ps: NPM是基于命令行的node包管理工具,它可以将node的程序模块安装到项目中,在它的官网https://npmjs.org/ 中可以查看和搜索所有可用的程序模块。

1.3 定位到项目

直接输入d:  按回车键,进入d盘,再进入到安装文件夹,如下图:

2

1.4 安装gulp

遇到的问题:

参考资料中有sudo npm install –g glup安装命令,但是是出错的。

3

Sudo是以管理员身份执行命令,是切换到最高用户权限,su是切换用户,这是linux里才有的,windows是没有的。

将sudo去掉,用npm install -g gulp安装也是不行的。

4

使用npm install --global gulp是可以安装的,但是有一个warn警告。

5

查看版本号也是能查看到的:

6

二、开始使用gulp

2.1 新建gulpfile.js文件

建立gulpfile.js文件,作为它的主文件,放入到自己的项目目录中。

然后在gulpfile.js中定义自己的任务。

 

三、gulp-css-spriter

功能:将css代码中的切片图片合并成雪碧图

3.1 gulp-css-spriter使用步骤

(1)安装gulp-css-spriter

输入命令npm install gulp-css-spriter

7

安装成功后自己建的文件里会产生node_modules文件夹,里面会有一个刚安装的gulp-css-spriter文件夹。

89

(2)配置gulpfile.js文件

var gulp = require('gulp'),

spriter = require('gulp-css-spriter');

 

gulp.task('css', function(){

var timestamp = +new Date();

//需要自动合并雪碧图的样式文件

return gulp.src('styles/style.css')//雪碧图的原路径文件

.pipe(spriter({

// 生成的spriter的位置

'spriteSheet': 'combine/images/sprite'+timestamp+'.png',

// 生成样式文件图片引用地址的路径

// 如下将生产:background:url(images/sprite20160205.png)

'pathToSpriteSheetFromCSS': 'images/sprite'+timestamp+'.png'

}))

//产出路径

.pipe(gulp.dest('combine'));

});    //产出路径

2

(3)执行编译输入命令:gulp css

55

(4)编译前后文件目录截图对比

a.编译之前:

合并前文件目录:

11

合并前style.css样式:

22

合并前图片文件夹:

44

b.编译之后:

合并后文件目录:

66

combine文件夹里的文件:

77

combine里的style.css:

88

combine里的图片文件夹:

99

(5)可能出现的问题:

在编辑后可能会出现如下问题:

11

Cannot find module ‘gulp-minify-css’;

需要再次安装gulp-minify-css。执行命令:npm install gulp-minify-css

12

安装完毕后再次编译:(点击可查看动图编译过程)

15

 3.2  使用技巧

gulp-css-spriter默认会对样式文件里,所有的background/background-image的图片合并,但实际项目中,我们不是所有的图片都需要合并。

background-image: url(../images/data3.png?__spriter);//有?__spriter后缀的合并

background-image: url(../images/part-bg.png); //不合并

修改下面文件可以按需合并:

node_modules\gulp-css-spriter\lib\map-over-styles-and-transform-background-image-declarations.js

13

48行开始的if-else if代码块中,替换为下面代码

位置:

14

// background-image always has a url 且判断url是否有?__spriter后缀

if(transformedDeclaration.property === 'background-image' && /\?__spriter/i.test(transformedDeclaration.value)) {
transformedDeclaration.value = transformedDeclaration.value.replace('?__spriter','');
return cb(transformedDeclaration, declarationIndex, declarations);}
// Background is a shorthand property so make sure `url()` is in there 且判断url是否有?__spriter后缀
else if(transformedDeclaration.property === 'background' && /\?__spriter/i.test(transformedDeclaration.value)) {
transformedDeclaration.value = transformedDeclaration.value.replace('?__spriter','');
var hasImageValue = spriterUtil.backgroundURLRegex.test(transformedDeclaration.value);
if(hasImageValue) {
return cb(transformedDeclaration, declarationIndex, declarations);}
}

 

再次执行即可。

 

参考链接:

https://github.com/laoshu133/gulp-css-spritesmith

https://github.com/aslansky/css-sprite

 

sublime常用的插件介绍

整  理:肖雅君
时  间:2015-12-18
说  明:sublime常用的插件介绍

一、安装插件的基本条件

1. 前提

2. 两种安装方法

二、插件介绍

1. 插件emmet

2. Emmet LiveStyle

3. Bracket Highlighter插件

4. Trailing Spaces高亮空白区域

5. JsFormat:js格式化的插件

附:Barcakets插件安装:

插件位置:\\192.168.0.18\运维网络硬盘\y袁亮\p培训\55分享2015-12-16(前端)\sublime提高开发效率的几个插件

参考链接: http://www.cnblogs.com/hykun/p/sublimeText3.html

 

Sublime高效率前端编辑插件

一、安装插件的基本条件

1.前提:

(1)需要sublime text3

(2)安装任何插件都得先安装package control插件管理。

2.两种安装方法:

1)自动安装:先按键ctrl+` ,再将安装代码复制进去;

1

安装代码:import urllib.request,os,hashlib; h = 'eb2297e1a458f27d836c04bb0cbaf282' + 'd0e7a3098092775ccb37ca9d6b2e4b7d'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)

(2)手动安装:

直接下载Package Control插件,放到sublime安装目录下的Installed Packages目录下,如下图:

23

二、插件介绍

1. 插件emmet

缩写+自动生成-提高开发效率,需了解简单的语法规律

Emmet语法:http://yanxyz.github.io/emmet-docs/abbreviations/syntax/

2. Emmet LiveStyle

实时刷新双向修改

(1)第一步:安装插件

法一:

自动安装:ctrl+shift+p打开安装包管理器,输入PCI后,输入LiveStyle:如下图

5

法二:

手动安装:同上将插件放到Installed Packages目录下。

(2)第二步:在浏览器上安装Emmet LiveStyle插件

6

(3)第三步:使用步骤

用sublime打开样式文件;浏览器打开html文件后F12,即可看到安装后的插件:勾选Enable LiveStyle for current page,再将样式文件的目录复制到liveStyle里即可。然后就能实行双向修改了。如下图:

7

3.  Bracket Highlighter插件

用于匹配括号,引号和html标签。

对于很长的代码很有用。安装好之后,不需要设置插件会自动生效.【安装过程同上】

图示:

9

如图:如果代码的标签是成对的,则会显示两个小图标;如果标签并不是成对的,则会显示”小问号“。

10

4. trailing Spaces高亮空白区域

此插件自动将无效的有空白区域的代码显示出颜色来。

一键删除所有空格设置:

需要配置快捷键:在preferences/key binding-user,加上如下代码:

{ "keys": ["ctrl+shift+t"], "command": "delete_trailing_spaces" }

操作如下图:

1112

5. JsFormat

js格式化的插件,安装方式同上,效果图如下:19

附:Barcakets开发软件的插件安装方法

(1)emmet 直接点击右边的小商品标志

13

输入插件名,自动安装完毕:

14

(2)显示小图标插件:Brackets Icons

效果图如下:

16

参考链接: http://www.cnblogs.com/hykun/p/sublimeText3.html

http://www.xuanfengge.com/practical-collection-of-sublime-plug-in.html

 

注:若是直接拷贝插件安装,需注意几个插件安放的位置不一样:

插件位置:\\192.168.0.18\运维网络硬盘\y袁亮\p培训\55分享2015-12-16(前端)\sublime提高开发效率的几个插件

(1)两个插件文件夹放在:Packages文件夹下,通过Preferences>Browse Packages打开:

17(2)非文件夹插件放在Packages上级的Install Packages目录下:

18

 

育网专题评论区改版

整    理:肖雅君

时    间:2015-12-04

更    新:2016-02-26

说    明:育网专题PC端和WAP端使用本公司开发的评论区修改步骤

 

一、PC端

1.公共头部

2.评论部分

二、WAP端

1.添加手机端评论样式

2.头部添加代码

3.底部添加代码

4.分享

 

PC端和WAP端评论区改版

头部+导航+底部+评论区

以前PC端和手机端的的评论部分都是用的“畅言”(畅言是搜狐推出的社会化评论及聚合平台)。但以后育网专题都会采用育儿网仿畅言做出来的评论。暂时尚未做成后台,所以需要前端手动添加各种文档、修改参数。

一、PC

  1. 公共头部

简介:育网公共头部,包含导航和登录的php文件以及头部样式引入。

添加方式:无需拷贝文件,无需改变路径,只需要在对应位置添加两串固定代码。

添加位置:  

<html>
<head>
<?php include "../global/meta.php";?>
</head>
<body>
<?php include "../global/header.php";?>
</body>
</html>

2.“评论”部分

(1)引入评论:

在<!DOCTYPE html>前添加如下代码:

<?php
include_once('../include/global.php');
$id = 11742336;//帖子ID
?>

(2)修改方式:

后台操作:

专题后台链接:http://www.ci123.com/special/sadmin/clearup_list.php?page=4

编辑那边通过后台发布的评论页面有可能是.html文件,(如:http://www.ci123.com/special/sadmin/recommend/recommend.php?code=piyao-ceqie.html),.html文件对应的是“畅言”的评论。

转成育网评论需在后台操作,步骤如下:

将“是否使用妈妈社区评论”选择“是”:

2

本地操作:

第一步:在index.php中添加两个样式文件(固定链接):

在index.php的<head>部分添加“左侧评论块”和右侧“专题推荐”部分的样式文件:

<link rel="stylesheet" href="http://www.ci123.com/special/dajiashuo-pc/styles/reply.css">

<link href="http://www.ci123.com/special/recommend/css/recom-wqhg.min.css" rel="stylesheet" type="text/css">

(*注:“dajiashuo-pc/styles/reply.css”是公共样式,部分专题都已使用这个样式,除非所有的专题评论区都存在共性的问题,否则不得直接修改这个样式文件。只能在自己写的样式文件里写入新样式覆盖dajiashuo-pc的样式。)

第二步:引入评论区:

在index.php的评论部分添加如下代码:

<?php include_once("../recommend/piyao-ceqie.php");?>

第三步:修改帖子ID【重要】

【重要】不同专题的帖子ID是不一样的。同一个专题的手机端和PC端的帖子ID是同样的。

 

二、WAP端

1.添加手机端评论样式

WAP端只需添加一个样式文件。

<link rel="stylesheet" href=" http://m.ci123.com/special/dajiashuo_wap/styles/reply.css">

2.顶部

包括:PC端/WAP端的链接跳转,育网APP分享,代码如下:

<?php
include_once('../inc/global.php');
if(getOsNew()== 'pc'){
header('Location:http://www.ci123.com/special/survey-ceqie/');//链接为专题PC端的链接
exit;
}
$post_id = 10724610;//帖子ID,重要!每一期都要修改
$url = '专题手机端的访问链接';
$share_pic = '专题分享图片';
$msg = '专题分享文案';
$title = '专题标题';
?>
<!DOCTYPE html>
<html>
</html>

3.底部

包括:评论部分+制作团队+“妈妈社区APP推广”+底部版权

重点是评论以及“妈妈社区”,代码如下:

<div class="weibo">
<div class="say"><i></i><span>大家都在说</span></div>
<?php include_once('../inc/reply.php');?>
</div><!--weibo-->
<div class="part-team">
</div><!-制作团队-->
<?php
if($_COOKIE['uid']>0&&strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') === false){
?>
<?php } else {?
<a href="http://app.ci123.com/down/bbs.php?type=2" class="app_pro">
<img src="http://m.ci123.com/special/piyao-gudaiyunyu/images/download.png" width="100%">
</a>
<?php }?>
<div class="footer">
</div><!--版权所有-->

4.分享

简介:手机端另一个和往期专题不同变化是分享。

现在的分享采用两种方式,一种是在微信朋友圈推广,采用微信自带的分享方式。另一种是在妈妈社区APP或是育网APP上的分享按钮。

后端已对这两种方式进行了处理,只有在APP上才会显示分享按钮,微信上并不显示。

但是前端这两种方式都要顾及到,所以需要前端修改两个地方的分享文案

添加方式:

1.添加微信分享:

在index.php中添加如下代码:

<!--微信分享内容区域-->

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script src="http://m.ci123.com/special/weixin/wx_share.js"></script>
<script type="text/javascript">
$.getJSON('http://m.ci123.com/special/weixin/getAuth.php?PackageUrl='+encodeURIComponent(window.location.href),function(data){
callWeiXin(data);
wxShare('侧切会影响产后“性福”?','顺产侧切真的会影响产后性生活吗?《育网辟谣》告诉你真相!','http://m.ci123.com/special/piyao-ceqie','http://m.ci123.com/special/piyao-ceqie/images/share1.jpg');
});
</script>
<?php include_once('../inc/app_share.php');?>

<!--end 微信分享内容区域-->

 

【前端技术文档】CSS3 Animation 动画属性

整 理:肖雅君、曹燕

时 间:2015-11-05

说 明:animation属性的介绍和简单的用法


一、兼容性

二、语法介绍

1 定义keyframes语法

1.1 语法

1.2 值和描述

2 调用动画语法

2.1 语法

2.2 属性值

3 属性值详解

3.1 animation-duration

3.2 animation-timing-function

3.3 animation-iteration-count

3.4 animation-direction

三、综合示例

 

 

Animation

一、兼容性

Chrome 13+、Firefox 5+、Safari 5.1+、Opera 12+、IE10+均支持animation

常用前缀:

Firefox:-moz

Safari 和 Chrome:-webkit

Opera :-o

 

二、语法介绍

1 定义keyframes语法

@keyframes 规则用于创建动画。在 @keyframes 中规定某项 CSS 样式,就能创建由当前样式逐渐改为新样式的动画效果。

1.1 语法

@keyframes animation-name{keyframes-selector {css-styles;}}

1.2 值和描述

animation-name:(必需)指定要绑定到选择器的关键帧的名称,即动画的名称。

keyframes-selector:(必需)动画时长的百分比。

建议: 在CSS3中,我们以百分比来规定改变发生的时间,或者通过关键词“from”和”to”,等价于0%和100%,其中,0%是动画的开始时间。100%是动画的结束时间。

例如:

@keyframes colorchange {

0%   { background-color:#00f; /* from:blue */ }

25%  { background-color:#f00; /* red       */ }

50%  { background-color:#0f0; /* green     */ }

75%  { background-color:#f0f; /* purple    */ }

100% { background-color:#00f; /* to: blue  */ }

}

@-webkit-keyframes colorchange {

0%   { background-color: #00f; /* from:blue */ }

25%  { background-color: #f00; /* red       */ }

50%  { background-color: #0f0; /* green     */ }

75%  { background-color: #f0f; /* purple    */ }

100% { background-color: #00f; /* to: blue   */ }

}

解释:这个例子中定义了background-color这个属性。其中0%这可以用from关键字来代替,100%可以用to代替。即:

@keyframes colorchange {

from  { background-color: #00f; /* from: blue */ }

25%  { background-color: #f00; /* red         */ }

50%  { background-color: #0f0; /* green       */ }

75%  { background-color: #fF0f; /* purple     */ }

to  { background-color: #00fF; /* to: blue    */ }

}

2 调用动画语法

2.1 语法

animation:name duration timing-function delay iteration-count direction;

例:animation:changeColor 6s ease-in-out .2s infinite alternate;

2.2 属性值

animation属性是一个简写属性,用于设置动画的属性。

animation-name:该属性主要是用来调用@keyframes定义好的动画。

animation-duraton:动画指定需要多久完成,默认是0。

animation-timing-function:设置动画的速度曲线,默认是”ease”。

animation-delay: 设置在动画将启动之前经过的延迟间隔,默认是0。

animation-iteration-count:设置动画周期的播放次数,默认是1。

animation-direction:设置对象动画在循环中是否反向运动,默认是“normal”。

 

3 属性值详解

3.1 animation-duration

指定动画需要多久完成。请始终规定animation-duration属性,否则时长为0,就不会播放动画了。

3.2 animation-timing-function

animation-timing-function值

ease:默认值,元素样式从初始状态过渡到终止状态时速度由快到慢,逐渐减慢。

liner:元素样式从初始状态过渡到终止状态速度是恒速。

ease-in:元素样式从初始状态过渡到终止状态时,速度越来越快,呈一种加速状态。常称这种状态为渐显效果。

ease-out:元素状态从初始状态过渡到终止状态时,速度越来越缦。呈一种减速状态。常称这种状态为渐隐效果。

ease-in-out:元素样式从初始状态到终止状态时,先加速再减速。常称这种效果为渐显渐隐效果。

3.3 animation-iteration-count

指定动画的播放次数,取值可以是:

n:即具体的数字,表示具体的播放次数;

infinite:表示无数次播放。

3.4 animation-direction

有四个值:

normal:默认,从0%到100%;

reverse:动画从100%执行到0%;

alternate:动画在0%到100%之间往复执行;

alternate-reverse与alternate一致,不过是从100%开始。

 

三、综合示例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>animation</title>

<style>

@keyframes slide{

0%   {background:#f00; left:0px; top:0px;} /* from: red */

100%  {background:#fefe00; left:200px; top:0px;} /* to: yellow */

}

@-moz-keyframes slide{

0%   {background:#f00; left:0px; top:0px;}/* from: red */

100%  {background:#fefe00; left:200px; top:0px;} /* to: yellow */

}

@-webkit-keyframes slide{

0%   {background:#f00; left:0px; top:0px;}/* from: red */

100%  {background:#fefe00; left:200px; top:0px;} /* to: yellow */

}

@-o-keyframes slide{

0%   {background:#f00; left:0px; top:0px;}/* from: red */

100%  {background:#fefe00; left:200px; top:0px;} /* to: yellow */

}

.box{

width:100px;

height:100px;

background:red;

position:relative;

animation:slide 5s linear 2s infinite alternate;

/* Firefox: */

-moz-animation:slide 5s linear 2s infinite alternate;

/* Safari and Chrome: */

-webkit-animation:slide 5s linear 2s infinite alternate;

/* Opera: */

-o-animation:slide 5s linear 2s infinite alternate;

}

</style>

</head>

<body>

<div class="box"></div>

</body>

</html>

说明:这段代码首先用@keyframes定义了一个名称为“slide”的动画,效果是使一个背景为红色的元素从左向右滑动200px,同时背景色变为黄色;然后将这个动画效果和box类绑定,使这个动画:先延迟2s、然后无限循环播放此动画、5s完成一次动画、每次动画都以匀速演示、奇数次动画正向播放、偶数次动画逆向播放。

 

【前端技术文档】Position定位详解

整    理:肖雅君、曹燕

时    间:2015-10-30

说    明:position定位详解

一、兼容性

二、文档流

三、定义和用法

1.position介绍

1.1 说明

1.2 主要的值

1.3 辅助属性

2.position定位方式

2.1 position: static

2.2 position:relative

2.3 position:absolute

2.4 position:fixed

2.5 z-index

三、用途

1.布局

2.设置垂直居中

3.设置全屏

4.固定内容位

 

 

 

一、兼容性

所有的主流浏览器都支持position属性。

二、文档流

含义:将窗体自上而下分成一行行, 并在每行中按从左至右的顺序排放元素,即为文档流。

只有3种情况会使得元素脱离文档流,分别是:浮动、绝对定位、固定定位。

三、定义和用法

1.position介绍

1.1 说明

position属性规定元素的定位类型,也就是说元素脱离文档的布局后,在页面的任意位置显示。

1.2 主要的值

(1) 默认值:static,无特殊定位,即不设定元素的position属性时,position值是static。它遵循正常的文档流对象,对象占用文档空间。在该定位方式下top、right、bottom、left、z-index等属性是无效的。

(2) relative:相对定位,不脱离文档流的布局,还在文档流原先的位置遗留空白区域。定位的起始位置为此元素原先在文档流的位置。

(3)absolute:绝对定位,脱离文档流的布局,遗留下来的空间由后面的元素填充。定位的起始位置为最近的父元素(position不为static),否则为body文档本身。

(4)fixed:固定定位,脱离文档流,相对于浏览器窗口进行定位,不随着滚动条的移动而改变位置。

(5)inherit:规定从父元素继承position属性的值。

1.3 辅助属性

position属性要想使元素脱离文档流后按照希望的位置显示,就需要使用下面的属性(position:static不支持这些):

(1)left:表示向元素的左边插入多少像素,使元素向右移动多少像素。

(2)right:表示向元素的右边插入多少像素,使元素向左移动多少像素。

(3)top:表示向元素的上方插入多少像素,使元素向下移动多少像素。

(4)bottom:表示向元素的下方插入多少像素,使元素向上移动多少像素。

2.position定位方式

2.1 position: static

2.1.1 static详解

(1默认值static通常都会影响到元素的位置。主要是看元素本身是block属性或是inline属性。

如下图,两个<div>因为是block的关系,所以就会上下各占据一行,那如果是两个<span>,因为是inline,所以会在同一行里呈现。

代码:.div1{width:50px;height:50px;background:#f1f411;}

.div2{width:50px;height:50px;background:#dfafda;}

.span1{background:#f1f411;}

.span2{background:#dfafda;}

13
 (2) static不能通过z-index进行层次分级。

 

2.2 position:relative

2.2.1 说明

相对定位。不脱离文档流的布局,在文档流的位置遗留空白区域。定位的起始位置为此元素原先在文档流的位置(即下图虚线部分)。
2
2.2.2 relative详解

(1)relative定位的top / right / left / bottom 属性是不会对相对定位的元素所占据的文档空间产生偏移的。
9如下图:.div1{position:relative;top:20px;left:20px;},而top值和left值并没有对div1原来的位置(即红色虚线部分)产生影响。

(2)元素的margin / padding会让该文档空间产生偏移,从而对定位产生影响。

对div1设置margin:20px;后
14
2.3 position:absolute

2.3.1 说明

绝对定位。a脱离文档流的布局,遗留下来的空间由后面的元素b填充。a定位是相对于距离a最近的父元素定位,且父元素的postion不为static,否则就相对于body文档本身定位。

 12.3.3 absolute详解

absolute定位,也称为绝对定位,虽然它的名字号曰“绝对”,但是它的功能却更接近于"相对"一词,为什么这么讲呢?原来,使用absolute定位的元素脱离文档流后,就只能根据祖先类元素(父类以上)进行定位,而这个祖先类还必须是以postion非static方式定位的。

这里还需要注意的是,relative和static方式在最外层时,是以<body>标签为定位原点的,而absolute方式在无父级是position非static定位时,是以<html>作为原点定位。

如下图,示例1的最外层wrapper层未设置position,则第一个子级a是相对于body定位,子子级a-1和a-1-1都是相对于临近的设置了position的父级定位的;而示例2的最外层设置了position,则a是相对于wrapper定位的。示例3的a-1未设置position,则子级a-1-1是相对于临近的设置了定位的a进行的定位。
56
(2使用absolute或fixed定位的话,必须指定 left、right、 top、 bottom 属性中的至少一个,否则left/right/top/bottom属性会使用它们的默认值auto,此时该元素也是脱离文档流的。

(3少了left/right/top/bottom属性不行,那如果多设了呢?例如,同时设置了top和bottom的属性值,那元素又该往哪偏移好呢?记住下面的规则:

        如果top和bottom一同存在的话,那么只有top生效。

        如果left和right一同存在的话,那么只有left生效。

        与top/bottom/left/right的书写顺序无关。

(4绝对(absolute)定位对象在可视区域之外会导致滚动条出现,而相对(relative)定位对象在可视区域之外,不会出现滚动条。

 

2.4 position:fixed

2.4.1 说明

固定定位。类似于absolute,但不随着滚动条的移动而改变位置。
3

2.5 z-index

z-index属性,又称为对象的层叠顺序,它用一个整数来定义堆叠的层次,整数值越大,则被层叠在越上面,当然这是指同级元素间的堆叠。

如果两个对象的此属性具有同样的值,那么将依据它们在HTML文档中流的顺序层叠,写在后面的将会覆盖前面的。

需要注意的是,父子关系是无法用z-index来设定上下关系的,一定是子级在上父级在下。

 

三、用途

1.布局
4
2.设置垂直居中

例:在移动端,由于设备宽高不固定,所以对<div>设置垂直居中需用到定位,用于匹配不同的移动设备。

.wrapper{position:relative}

.head{position:absolute;top:50%;left:50%;-webkit-transform: translate(-50%,-50%);-moz-transform: translate(-50%,-50%);-ms-transform: translate(-50%,-50%);-o-transform: translate(-50%,-50%);transform: translate(-50%,-50%); }

注意:这里定位是相对于.head的左上角定位,所以还需设置margin-top和margin-left,值为.head宽高的1/2(或者设置transition)。
7

3.设置全屏

常用于移动端,如:设置蒙层。

手机宽高不一定时,要保证弹出的蒙层全屏显示,可以用到position:absolute,代码如下:

.wrapper{position:absolute;top:0;bottom:0;left:0;right:0;}

效果图:
12
4.固定内容位

  如PC端页面侧栏广告、WAP端的分享按钮(如上图)、固定位广告等。

 

【前端技术文档】公司前端项目规范文档

整 理:肖雅君、徐秀

时 间:2015-10-23

说 明:公司前端需遵守的项目规范


目录

第一节、 文档目录结构

第二节、 HTML书写规范

1、  声明和头部

2、  标签属性

第三节、 CSS书写规范

1、  外部引用样式

2、  格式化标签的默认样式:

3、  CSS书写规范

4、  CSS样式规范

第四节、 图像处理

1、  图像压缩

2、  图片格式

3、  Sprite雪碧图

第五节、  通用

1、  编码格式UTF-8

2、  书写小写

3、  去掉多余空格

4、  加注释

5、  特殊符号

6、  内部js代码的位置

附录:

参考链接:

 


第一节 、文档目录结构

  |-- 前端项目名
      |-- index.html /*存储HTML文件以及PHP文件*/
      |-- styles
          |-- images /*存储样式引入的图片,如公共图片*/
          |-- style.css /*存储CSS样式文件,默认初始命名为style.css*/
      |-- js /*存储js文件*/
      |-- images /*存储<img>标签所用图片,一般为数据调取的图片*/
      |-- global /*放置公共引用的模块,如多个页面引用的header和footer部分*/

第二节、HTML书写规范

1、声明和头部

1.1 PC端固定头部(公司统一)(见附录)

1.2 WAP端固定头部(公司统一)(见附录)

2、标签属性

2.1 缩进与换行

设置 4 个空格做为一个缩进层级,不允许使用 2 个空格 或 tab 字符与空格的混合。

2.2 闭合标签

所以的标签都必须闭合。非成对标记必须以“/>”结尾,且“/”前必须有一个空格,如<img />、<input />、<br />等。

2.3 标签语义化

如:<h1>到<h6>的定义,应遵循从大到小的原则,体现文档的结构,有利于搜索引擎的查询。

2.4 标签简洁化

标签的嵌套应尽量简洁,减少嵌套层次,减少不必要的的标签。

如:<!-- good -->
   <img class="avatar" src="image.png" />

   <!-- bad -->
   <span class="avatar">
         <img src="image.png">
   </span>

2.5 类名或id名命名规则

(1)类名或id名命名要在保证通俗易懂的前提下尽量简洁。
1

(2)同一页面内,禁止使用相同的 name 与 id

2.6 连字符

id、class 命名必须单词全字母小写,class 命名单词间以“中划线”分隔;id 命名多个单词使用“下划线”连接。如<div class="goods-list"></div>。

2.7 布尔类型的属性

布尔类型的属性,不添加属性。如:<input type="text" disabled />

第三节、CSS书写规范

1、外部引用样式

所有的样式文件都写到css文件中,使用<link rel="stylesheet" href="styles/style.css" />引入到页面中。优先使用“外部样式表”,不建议使用内嵌样式,实际情况按后端需求。

2、格式化标签的默认样式:

2.1 PC端格式化样式(见附录2.2 WAP端格式化样式(见附录)

3、CSS项目书写规范

3.1 简洁型书写格式

实际项目中需压缩CSS样式,所以使用样式属性单行书写的格式,且去除多余空格。
样式紧接着选择器写,样式之间不能有空格,同一选择器的样式不换行。
2

3.2 写上父级类名

禁止使用*选择符。嵌套的类名很多的时候,需把父级也写上,当超过5个类名时可省略父级:如下

4、CSS样式规范

4.1 简化CSS属性

如font、margin、padding、border等。

    <!-- bad -->
    border-left:0;border-top:5px;border-right:0;border-bottom:5px;

    <!--good -->
    border:0 5px;

4.2 0和单位

(1)0后省略单位,非0数值必须加上单位。如:width:5px;height:0;

(2)属性值出现小数点忽略0,如:font-size:.8em;

4.3 a标签

a标签伪类书写要严格按照a:link,a:visited,a:hover,a:active的顺序,否则在某些浏览器中会失效。

4.4 简写颜色

如果不是为了制作半透明效果,颜色值必须使用十六进制记号形式 #rrggbb,颜色能简写的要简写,且颜色值使用小写字母。如:用{color:#f00;}代替{color#red;}和{color:#ff0000;}。

4.5 清浮动

在html中添加类名“.clearfix”,样式文件中添加代码

如:html中<div class="wrapper clearfix"></div>

CSS样式:4

第四节、图像处理

1、图像压缩

所有图片必须经过一定的压缩和优化才能发布(压缩软件:PNGGauntlet可压缩PNG图片)。

2、图片格式

用png图片做图片时, 要求图片格式为png-24格式,用png-8为ie6单独定义背景。WAP端默认用png-24。

3、Sprite雪碧图

能用雪碧图的尽量做成雪碧图(CSS Sprite是一种将数个图片合成为一张大图的技术,既可以是背景图也可以是前景图)。在一个位置统一调用背景图片,然后通过偏移background-position来进行图像位置选取;

使用url()时忽略括号中的""。如:5

第五节、通用

1、编码格式UTF-8

不管是HTML还是CSS文件,都统一采用UTF-8编码格式

2、书写小写

所有的html代码、CSS代码、颜色值等必须要用小写。

3、去掉多余空格

不管是html文件还是CSS文件,都不要有多余的空格。(sublime有插件能显示并一键删除所有多余空格:trailing Spaces)
6
2

(*注:以上演示图片中部分图片为了清楚的显示和对比样式,采用了换行显示,实际做项目时不能换行不能有空格。)

4、加注释

(1)给重要的区块加上注释,如:给重要图片加上 alt 标签。

(2) 给区块代码及重要功能(比如循环等),需在区块的开始或结尾添加注释。(另注释太多,在 ie6 下会有bug,故酌情添加。)

5、特殊符号

特殊符号使用代码替代,如<用&lt;替代、>用&gt;替代等。

6、内部js代码的位置

如果 js 文件只是要实现某些功能(比如点击按钮事件),那就在底部</body>前引入它。如:
   <body>
         <div>
         </div>
   <script>
   </script>
   </body>

 
附录:

1、PC端(公司统一)

<!DOCTYPE html>
<html> 
<head> 
<meta charset="UTF-8"> 
<title></title> 
<meta name="renderer" content="webkit"> 
<meta http-equiv="X-UA-Compatible" content="IE=Edge"> 
<meta name="keyword" content="">
<meta name="description" content=""> 
<link rel="stylesheet" href="styles/style.css"> 
</head> 
<body> 
/* HTML代码 */
<script src="http://file2.ci123.com/ast/js/jquery_172.js"></script> 
</body> 
</html>

2、Wap端(公司统一)

<!DOCTYPE html> 
<html> 
<head> 
<meta charset="UTF-8"> 
<title></title> 
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> 
<meta name="format-detection" content="telephone=no">
<meta name="apple-mobile-web-app-capable" content="yes"> 
<meta name="apple-mobile-web-app-status-bar-style" content="black"> 
<link rel="stylesheet" href="styles/style.css">  
</head> 
<body> 
/* HTML代码 */
<script src="http://file2.ci123.com/ast/js/zepto.js"></script> 
</body> 
</html>

3、PC端格式化样式

body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{margin:0;padding:0}body,button,input,select,textarea{font-family:Arial,"Microsoft Yahei","Hiragino Sans GB","WenQuanYi Micro Hei",sans-serif;font-size:12px;}h1,h2,h3,h4,h5,h6{font-size:100%}address,cite,dfn,em,var{font-style:normal}ul,ol{list-style:none}sup{vertical-align:text-top}sub{vertical-align:text-bottom}legend{color:#000}fieldset,img{border:0}button,input,select,textarea{font-size:100%}table{border-collapse:collapse;border-spacing:0}a{text-decoration:none;}a:link,a:visited{color:#000;text-decoration:none;}a:hover{color:#c00;text-decoration:underline}img{border:0;-ms-interpolation-mode:bicubic}.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.clearfix{*zoom:1;clear:both;}* html>body .clearfix{display:inline-block;width:100%}* html .clearfix{/*\*/height:1%;/**/}*+html .clearfix{min-height:1%}

4、WAP端格式化样式

body{padding:0;margin:0;font-size:14px;font-family:Arial;}h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{margin:0;padding:0;}dl,dt,dd,ul,li,ol{list-style:none;}img{border:0;}.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden} .clearfix{clear:both;}table{border-collapse:collapse;border-spacing:0;} 


参考链接:

公司后台前端开发文档:
http://abc.ci123.com/admin/tech/shareexp/list.php?cpage=4 
HTML编码规范:http://blog.geekman.vip/archives/353
CSS编码规范:http://blog.geekman.vip/archives/352