Sass mixin制作水平垂直居中

整   理:晋 哲

时   间:2017-01-06

说   明:使用Sass mixin 的方式将一些固定样式用法封装起来,能够提高样式复用性。

如水平垂直居中的示例:
常用的水平垂直居中方式是使用CSS transform属性或负向margin的方式,将这两种方法集成起来,通过判断是否有宽高值生成对应的样式。

/*定义mixin*/
@mixin center($width: null, $height: null){
     position: absolute;
     top: 50%;
     left: 50%;

     @if not $width and not $height{
          transform: translate(-50%, -50%);
     }
     @else if $width and $height{
          width: $width;
          height: $height;
          margin: -($height/2) #{0 0} -($width/2);
     }
     @else if not $height{
          width: $width;
          margin-left: -($width/2);
          transform: translate(0, -50%);
     }
     @else{
          height: $height;
          margin-top: -($height/2);
          transform: translate(-50%, 0);
     }
}

/*使用*/
.box1{
     @include center;
}
.box2{
     @include center(200px);
}
.box3{
     @include center(null, 300px);
}
.box4{
     @include center(200px, 300px);
}

CSS3 Animation steps()函数属性运用

整   理:晋 哲

时   间:2017-01-06

说   明:利用steps()函数的特效可以制作类gif动画的动态效果,搭配sprite图使用。

作用优势:代替gif动图的繁琐制作,调整动画便捷,较gif更清晰,图片进行压缩,文件可更小。

使用说明:animation的steps()函数内部的第一个参数设置为正整数,可以计算等分@keyframes规则内from到to的差值,最终进行动画切换。

如示例代码:

.dragon{
    width: 178px;
    height: 188px;
    background: url(images/dragon.png) 0 0 no-repeat;
    animation: run_dragon 2s steps(10) infinite;
}
@keyframes run_dragon{
    0%  {background-position: 0 0;}
    100%{background-position: -1780px 0;}
}

dragon

IOS键盘弹出导致fixed定位错位

整   理:晋 哲

时   间:2017-01-06

说   明:主要是input的焦点事件触发弹出键盘导致fixed定位失效,安卓没有该bug

方法一:使用absolute模拟fixed
1、当触发事件时,将固定定位的元素设置为【position:absolute;top:0;】
若页面高度一屏之内,则事件结束后还原样式即可;若页面很长则继续下一步

2、当页面滚动时,添加滚动事件,更新top值,使其看似一直在顶部

window.onscroll=function(){
    $(".fixed").css("top",$(window).scrollTop());
}

缺点:因为top值时实时计算的,页面滚动时,会有缓冲时间。

方法二:将溢出内容部分设置内部滚动,设置样式【…height:100vh;overflow:auto;】
因为键盘弹出时fixed失效,元素的位置自动根据scrollTop滚动的距离去定位,所以当页面高度为屏幕高度时,系统自动的定位也就在顶部了。

优点:该方法不需要再去设置复杂的js,仅设置样式即可,也是最常用的方法。

缺点:正常情况下是没有问题的,需注意的是商品列表中商品图片使用了lazyload.js,当内容部分设置overflow后,懒加载就失效了,因为它默认是整段body进行滚动监听的。解决方法:lazyload.js有参数【container】可以设置内部框架懒加载的。

解决前:
pic1

解决后:
pic2

vueJs父子组件通信以及vue-resource的使用

整   理:晋 哲

时   间:2017-01-03

说   明:实例展示vueJs如何调取数据

一、父子组件基本代码块

/* 父组件 */
<div id="product_list">
    <nav-item></nav-item>
</div>

/* 子组件模块 */
<template id="nav-model">
    ……
</template>

/* 子组件对象 */
Vue.component('nav-item', {
    template: '#nav-model',
    ……
});

/* 主体构造器 */
var ins = new Vue({
    el: '#product_list',
    data: [
        ……
    ],
});

二、父子组件自定义事件,用于在组件树中通信
使用 $on() 监听事件;
使用 $emit() 在它上面触发事件;
使用 $dispatch() 派发事件,事件沿着父链冒泡;
使用 $broadcast() 广播事件,事件向下传导给所有的后代。

三、常用父子组件通信方式
1、父组件向子组件传递数据
使用 Props 传递数据

2、子组件向父组件传递数据
使用 $on() 监听事件;
使用 $emit() 在它上面触发事件。

四、vue-resource的使用(在一个Vue实例内使用$http)
1、GET请求
this.$http.get('/someUrl', [options]).then(successCallback, errorCallback);

2、POST请求
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);

参考网址:
http://vuejs.org.cn/guide/components.html#使用-v-on-绑定自定义事件
http://www.doc00.com/doc/1001004eg

实例代码请看源代码
vue实例-保险列表

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

Bootstrap基础运用示例

整   理:晋 哲

时   间:2016-11-15

说   明:整理后台常用到的Bootstrap元素结构,便于规范运用

本地示例:http://192.168.0.100/BootstrapDemo.html

1、标题及下面的按钮
想要上下元素有间距,使用【form-group】父类包裹起来

bootstrap_pic1

<div class="form-group">
    <h3>标题文字</h3>
</div>
<div class="form-group">
    <button class="btn btn-success">新增模版</button>
</div>

2、功能按钮,分别对应【primary、success、info、danger、warning、default】
bootstrap_pic2

<button class="btn btn-primary">保存/提交/确认</button>
<button class="btn btn-success">添加/新建/通过</button>
<button class="btn btn-info">信息/详情/查看数据</button>
<button class="btn btn-danger">删除</button>
<button class="btn btn-warning">修改/审核/警告</button>
<button class="btn btn-default">默认/普通</button>

元素右对齐,使用【pull-right】
bootstrap_pic2_1

<div class="form-group">
    <button class="btn btn-success">新增模版</button>
    <button class="btn btn-primary pull-right">保存</button>
</div>

3、用于表单中的文字按钮
bootstrap_pic3

<button class="btn btn-link">编辑</button>
<button class="btn btn-link">删除</button>

<a class="btn btn-link btn-sm" href="#">编辑</a>
<a class="btn btn-link btn-sm" href="#">删除</a>

<a class="btn btn-link btn-xs" href="#">编辑</a>
<a class="btn btn-link btn-xs" href="#">删除</a>

4、内页分类标题
bootstrap_pic4

<div class="breadcrumb">1、类目选择</div>
<div class="breadcrumb">2、基本信息</div>
<div class="breadcrumb">3、商品规格</div>

如果想要调整字体大小,可以改动<div>标签,使用标签<h3>、<h4>
bootstrap_pic4_2

<h3 class="breadcrumb">1、类目选择</h3>
<h4 class="breadcrumb">1、类目选择</h4>

5、表单,使用【form-horizontal】包裹起来
bootstrap_pic5

<div class="form-horizontal">
    <div class="form-group">
        <label class="col-sm-2 control-label">用户名:</label>
        <div class="col-sm-5"><input type="text" class="form-control"></div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">密码:</label>
        <div class="col-sm-5"><input type="text" class="form-control"></div>
    </div>
</div>

如果没有label标题,又需要表单对齐的,使用【col-sm-offset-*】

<div class="form-group">
    <div class="col-sm-offset-2 col-sm-5">
        <button class="btn btn-primary">保存</button>
    </div>
</div>

6、水平排列的表单,使用【form-inline、radio-inline、checkbox-inline】
bootstrap_pic6

<div class="form-horizontal">
    <div class="form-group form-inline">
        <label class="col-sm-2 control-label">有效期:</label>
        <input type="text" class="form-control"> 至 <input type="text" class="form-control">
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">单项选择:</label>
        <label class="radio-inline"><input type="radio" name="option1" value="选项一"> 选项一</label>
        <label class="radio-inline"><input type="radio" name="option1" value="选项二"> 选项二</label>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">多选选择:</label>
        <label class="checkbox-inline"><input type="checkbox" value="选项一"> 选项一</label>
        <label class="checkbox-inline"><input type="checkbox" value="选项二"> 选项二</label>
    </div>
</div>

7、多列展示,使用栅格样式
bootstrap_pic7

<div class="form-horizontal">
    <div class="form-group">
        <div class="form-group col-sm-4">
            <label class="col-sm-4 control-label">多列设置:</label>
            <div class="col-sm-8"><input type="text" class="form-control"></div>
        </div>
        <div class="form-group col-sm-4">
            <label class="col-sm-4 control-label">多列设置:</label>
            <div class="col-sm-8"><input type="text" class="form-control"></div>
        </div>
        <div class="form-group col-sm-4">
            <label class="col-sm-4 control-label">多列设置:</label>
            <div class="col-sm-8"><input type="text" class="form-control"></div>
        </div>
    </div>
</div>

8、分页
bootstrap_pic8

<nav>
    <ul class="pagination">
        <li><a href="#"><span>上一页</span></a></li>
        <li class="active"><a href="#">1</a></li>
        <li><a href="#">2</a></li>
        <li><a href="#">3</a></li>
        <li><a href="#">4</a></li>
        <li><a href="#">5</a></li>
        <li><a href="#"><span>下一页</span></a></li>
    </ul>
</nav>

9、开关控件
bootstrap_pic9

<!-- 引入开关控件CSS -->
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap-switch/3.3.2/css/bootstrap3/bootstrap-switch.min.css">

<!-- 开关控件HTML -->
<div class="switch" data-on="primary" data-off="info">
    <input type="checkbox" name="is_on" data-on-text="开启" data-off-text="关闭" checked />
</div>

<!-- 引入开关控件JS -->
<script src="http://cdn.bootcss.com/bootstrap-switch/3.3.2/js/bootstrap-switch.min.js"></script>
<script>
    $(function() {
        $('input[name="is_on"]').bootstrapSwitch();
        $('input[name="is_on"]').on('switchChange.bootstrapSwitch', function(event, state) {
            console.log(state);
        });
    })
</script>

10、模态框
bootstrap_pic10

<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">点击弹出模态框</button>

<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
                <h4 class="modal-title" id="myModalLabel">标题</h4>
            </div>
            <div class="modal-body">
                显示内容
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default">关闭</button>
                <button type="button" class="btn btn-primary">保存</button>
            </div>
        </div>
    </div>
</div>

11、表格
bootstrap_pic11

<table class="table table-bordered table-striped table-hover">
    <thead>
        <tr>
            <th>First</th>
            <th>Second</th>
            <th>Third</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
    </tbody>
</table>

artTemplate模板引擎

整   理:晋 哲

时   间:2016-11-15

说   明:使用模板引擎代替原本数组的push()方法和字符串拼接方式

一、使用方式
1、基础引用

<div id="content"></div>
<script src="template.js"></script>

2、模板搭建
使用一个type="text/html"的script标签存放模板;

<script id="test" type="text/html">
<h1>{{title}}</h1>
<ul>
    {{each list as value i}}
        <li>{{i + 1}} :{{value}}</li>
    {{/each}}
</ul>
</script>

3、数据渲染

<script>
var data = {
    title: '一、基础用法',
    list: ['列表1', '列表2', '列表3', '列表4', '列表5']
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;
</script>

二、语法
{{ 与 }} 符号包裹起来的语句则为模板的逻辑表达式。

1、输出表达式
对内容编码输出,如:{{ value }}

2、条件表达式

{{if admin}}
    <p>admin</p>
{{else if code > 0}}
    <p>master</p>
{{else}}
    <p>error!</p>
{{/if}}

3、遍历表达式

{{each list as value index}}
    <li>序列{{index}} :{{value.text}}</li>
{{/each}}

4、嵌入子模板

{{include 'template_name'}}

三、文档参考
https://github.com/aui/artTemplate

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 机制一样。

HTML5 history pushState/replaceState操纵浏览器的历史记录

整   理:晋 哲

时   间:2016-06-16

说   明:HTML5引进了history pushState()/replaceState()方法,可以操纵浏览器的历史记录

HTML5引进了history.pushState()方法和history.replaceState()方法,它们可以逐条地添加和修改历史记录条目。这些方法可以协同window.onpopstate事件一起工作。

一、pushState()方法
pushState()有三个参数:一个状态对象、一个标题(现在会被忽略),一个可选的URL地址。
状态对象(state object):一个JavaScript对象,设置状态对象之后会将其拷贝到popstate事件的state属性中,然后在popstate事件中可以通过获取state属性与创建的新历史记录条目关联。
标题(title):FireFox浏览器目前会忽略该参数,所以暂时可以传一个空字符串。
地址(URL):新的历史记录条目的地址。该参数是可选的,不指定的话则为文档当前URL。

二、replaceState()方法
history.replaceState()操作类似于history.pushState(),不同之处在于replaceState()方法会修改当前历史记录条目而并非创建新的条目。

三、popstate事件
每当激活的历史记录发生变化时都会触发popstate事件。如果被激活的历史记录条目是由pushState所创建,或是被replaceState方法影响到的,popstate事件的状态属性将包含历史记录的状态对象的一个拷贝。

实例:选项卡切换结合浏览器的前进与后退
普通的选项卡切换局部页面,点击“后退”会直接跳转到上一个页面;现结合history.pushState()方法和popstate事件,可以实现选项卡页面之间浏览器历史记录的前进与后退。

简易总结实现步骤:
1、使用pushState()方法添加一条新的历史记录条目,这时只是改变了浏览器URL内容;
2、每激活一次历史记录(比如点击后退),就会触发一次popstate事件,事件中获取的state属性就会随之改变,在这种状态下设置对应页面切换的代码即可。

示例代码:
history_pic

Ajax加载的页面同样存在无法前进与后退的状况,同理实现。

参考代码:
1、Ajax与HTML5 history pushState/replaceState实例-张鑫旭
http://www.zhangxinxu.com/wordpress/?p=3432
2、动漫酷网站
http://dmku.net
3、pjax是对ajax + pushState的封装
https://github.com/welefen/pjax

Highcharts数据可视化图表库

1.简介

   Highcharts是一款纯javascript编写的图表库,能够很简单便捷的在Web网站或Web应用中添加交互性的图表,Highcharts目前支持多达18种不同类型的图表。
在线演示:http://www.hcharts.cn/demo/index.php
Api文档:http://www.hcharts.cn/api/index.php
中文教程:http://www.hcharts.cn/docs/index.php

2.highcharts优势

  • 兼容性
    Highcharts支持目前所有的现代浏览器,包括IE6 +、ios、Android。Highcharts在标准浏览器中使用SVG技术渲染图形,在遗留的IE浏览器中使用VML技术来绘图。
  • 开源免费
    针对个人用户及非商业用途免费,并提供源代码下载,可任意修改。商业用途需要购买许可。
  • 纯Javascript
    Highcharts完全基于本地浏览器技术,不需要任何插件(例如Flash、java),不需要安装任何服务器环境或动态语言库支持,只需要两个js文件即可运行。
  • 图表类型丰富
    Highcharts目前支持直线图、曲线图、面积图、曲线面积图、面积范围图、曲线面积范围图、柱状图、柱状范围图、条形图、饼图、散点图、箱线图、气泡图、误差线图、漏斗图、仪表图、瀑布图、雷达图,共18种类型图表,其中很多图表可以集成在同一个图形中形成综合图。
  • 动态性
    提供丰富的API接口,方便在创建图表后对图表的任意点、线和文字等进行增加、删除和修改操作。
  • 图表导出和打印功能
    可以将Highcharts图表导出为PNG、JPG、PDF和SVG格式文件或直接在网页上打印出来。
  • 图表缩放
    可以设置图表的缩放,让你更方便查看图表数据。
  • 支持外部数据加载
    Highcharts支持多种数据形式,可以是Javascript数组、json文件、json对象和表格数据等。

3.安装使用方法

(1)页面引入jquery文件和highcharts.js文件
<script src="http://cdn.hcharts.cn/jquery/jquery-1.8.3.min.js"></script>
<script src="http://cdn.hcharts.cn/highcharts/highcharts.js"></script>
(2)创建放置图表的元素
<div id="container" style="min-width:800px;height:400px"></div>
(3)调用插件方法
$(function(){
   $('#container').highcharts({
       //配置参数
   });
});

4.基本组成

   通常情况下,Highcharts包含标题(Title)、坐标轴(Axis)、数据列(Series)、数据提示框(Tooltip)、图例(Legend)、版权信息(Credits)等,高级的还包括导出功能按钮(Exporting)、标示线(PlotLines)、标示区域(PlotBands)等。
Highcharts基本组成部分如下图所示:
图片1
Title
图表标题,包含标题和副标题(subTitle),其中副标题是非必须的。
Axis
坐标轴,包含x轴(xAxis)和y轴(yAxis)。通常情况下,x轴显示在图表的底部,y轴显示在图表的左侧。多个数据列可以共同使用同一个坐标轴,为了对比或区分数据,Highcharts提供了多轴的支持。
Series
数据列。图表上一个或多个数据系列,比如曲线图中的一条曲线,柱状图中的一个柱形。
Tooltip
数据提示框。当鼠标悬停在某点上时,以框的形式提示该点的数据,比如该点的值,数据单位等。数据提示框内提示的信息完全可以通过格式化函数动态指定。
Legend
图例。用不同形状、颜色、文字等 标示不同数据列,通过点击标示可以显示或隐藏该数据列。
Credits
图表版权信息。显示在图表右下方的包含链接的文字,默认是Highcharts官网地址。通过指定credits.enabled=false即可不显示该信息。
Exporting
导出功能按钮。通过引入exporting.js即可增加图表导出为常见文件功能。
PlotLines
标示线。可以在图表上增加一条标示线,比如平均值线等。
PlotBands
标示区域。可以在图表添加不同颜色的区域带,标示出明显的范围区域。

5.折线图实现代码

89

6.图表效果展示

(1)折线图
1
(2)柱状图
4
(3)饼图
5
(4)3D柱状图
3