移动端的那些积累

移动端特性

手机端的web页(H5)

跨平台(手机端、PC端)

基于webview

-webkit- 常用属性

http://ued.ctrip.com/webkitcss/   整理的webkit属性集合

<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalabel=no">

1、-webkit-appearance: none;     // 用于移IOS下移除原生样式

2、text-size-adjust: 100%;       // webkit内核浏览器可以让终端字体小于12px

    iPhone 和 Android 的浏览器纵向和橫向时自动调整字体大小的功能。通过 text-size-adjust 设为 none 或者 100% 关闭字体大小自动调整功能.
    html {
        font-family: "Helvetica Neue", Helvetica, STHeiTi, Arial, sans-serif;
        -ms-text-size-adjust: 100%;
        -webkit-text-size-adjust: 100%; 
    }

3、overflow-scrolling  硬件加速, 在body中设置

    body {
        /*height: 100%;*/
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch; 
    }

4、tap-highlight-color  用户点击iOS的Safari浏览器中的链接或JavaScript的可点击的元素时,覆盖显示的高亮颜色

    a {
        -webkit-tap-highlight-color: transparent;
    }

5、touch-callout  当触摸并长按住的时候,禁止或显示系统默认菜单

    a {
        -webkit-touch-callout: none
    }

    window.ontouchstart = function(e) {
        if (e.target.tagName === 'img')
                    e.preventDefault();
    }

6、pointer-events:none;

viewport 视图

<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />

width - 设置viewport宽度,为一个正整数,或字符串‘device-width’

height - 设置viewport高度,一般设置了宽度,会自动解析出高度,可以不用设置

initial-scale - 默认缩放比例,为一个数字,可以带小数

minimum-scale - 允许用户最小缩放比例,为一个数字,可以带小数

maximum-scale - 允许用户最大缩放比例,为一个数字,可以带小数

user-scalable - 是否允许手动缩放

不同屏幕的适配方案

通过响应式技术,在不同设备上使用同一套代码来展示

1、设置@media      2、rem       3、vw/vh

一、@media 媒体查询 

    @media screen and(min-width: 500px){    // 大于500px执行下面代码
            ...
    }

二、rem

    rem会根据根元素<html>的fontSize的大小来变化,需要运用js来计算根据屏幕宽度或来计算html的赋值

    1、普通CSS写法

        html { font-size: 16px; }
        div { width: 2rem; }

    2、Sass的工程: 

        前端构建中,完全可以利用scss来解决这个问题,例如我们可以写一个scss的function px2rem即: 
        @function px2rem($px){
            $rem : 37.5px;
            @return ($px/$rem) + rem;
        }

        调用
        height: px2rem(90px);
        width: px2rem(90px);

三、vw、vh

    上面两种不是特别完美,媒体查询不能做到等比例响应,rem需要js与css耦合在一起,而且vw/vh就不需要

    计算vm方法: 16 / 750 * 100 = 2.13vw;        // 16是px转rem的值,750

        html {
            font-size: 2.13vw;
        }

    vw: 视窗的宽度,视窗的宽度是100vw

    vh: 视窗的高度,视窗的高度是100vh

    vmin: 选取vw和vh中最小的那个

    vmax: 选取vw和vh中最大的那个

https://zhuanlan.zhihu.com/p/23968868
https://juejin.im/entry/59b00e46f265da2491513bcc

移动端概念

一、物理像素: 物理像素是屏幕的实际尺寸

二、设备独立像素: 设备像素与CSS像素之间的关系

三、设备像素比 dpr: 设备像素比 = 物理像素 / 设备独立像素;

    js获取设备像素比: window.devicePixelRatio        // devicePixelRatio = 物理像素 / 实际像素;

    iphoneX是3倍屏,其它都是2倍屏

    retina屏是超高像素密度屏,同样大小的屏幕上显示的像素点由1个变为多个,同样苹果设备的retina屏中,像素点1个变为4个

    1、根据不同的设备像素比来加载不同的图片

        // 例如图片宽高为: 200px*200px,那么写法如下
        .css{ width:100px;height:100px;background-size:100px 100px; }

        // 其它元素的取值为原来的1/2,例如视觉稿40px的字体,使用样式的写法为20px
        .css{ font-size:20px }

        // image-set设计Rentina背景图
        image-set,webkit私有属性,也是CSS4的属性,为解决Rentina屏幕下的图像而生。
        .css {
            background: url(images/bg.jpg) no-repeat center;
            background: -webkit-image-set(
            url(images/bg.jpg) 1x,     //支持image-set普通屏
            url(images/bg-2x.jpg) 2x); //支持image-set的Rentinan
        }

        // javscript的解决方案
        $(document).ready(function(){
            if (window.devicePixelRatio > 1) {
                var lowresImages = $('img');

                images.each(function(i) {
                    var lowres = $(this).attr('src');
                    var highres = lowres.replace(".", "@2x.");
                    $(this).attr('src', highres);
                });
            }
        });

    https://www.jianshu.com/p/c88e9489b583

四、设置不同像素比的响应样式

    /* 2倍屏 */
    @media only screen and (-webkit-min-device-pixel-ratio: 2.0){
        .bor-querymidea::after{
            -webkit-transform: scaleY(0.5);
            transform: scaleY(0.5);
        }
    }

    /* 3倍屏 */
    @media only screen and (-webkit-min-device-pixel-ratio: 3.0){
        .bor-querymidea::after{
            -webkit-transform: scaleY(0.33);
            transform: scaleY(0.33);
        }
    }

Meta

1、空白页基本meta标签

    <!-- 设置缩放 -->
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" />

    <!-- 可隐藏地址栏,仅针对IOS的Safari(注: IOS7.0版本以后,safari上已看不到效果) -->
    <meta name="apple-mobile-web-app-capable" content="yes" />

    <!-- 仅针对IOS的Safari顶端状态条的样式(可选default/black/black-translucent ) -->
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />

    <!-- IOS中禁用将数字识别为电话号码/忽略Android平台中对邮箱地址的识别 -->
    <meta name="format-detection"content="telephone=no, email=no" />


2、其他meta标签

    <!-- 启用360浏览器的极速模式(webkit) -->
    <meta name="renderer" content="webkit">

    <!-- 避免IE使用兼容模式 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
    <meta name="HandheldFriendly" content="true">

    <!-- 微软的老式浏览器 -->
    <meta name="MobileOptimized" content="320">

    <!-- uc强制竖屏 -->
    <meta name="screen-orientation" content="portrait">

    <!-- QQ强制竖屏 -->
    <meta name="x5-orientation" content="portrait">

    <!-- UC强制全屏 -->
    <meta name="full-screen" content="yes">

    <!-- QQ强制全屏 -->
    <meta name="x5-fullscreen" content="true">

    <!-- UC应用模式 -->
    <meta name="browsermode" content="application">

    <!-- QQ应用模式 -->
    <meta name="x5-page-mode" content="app">

    <!-- windows phone 点击无高光 -->
    <meta name="msapplication-tap-highlight" content="no">

预加载技术

一、dns-prefetch 预加载

    <link rel="dns-prefetch" href="http://g.alicdn.com">

    dns-prefetch, DNS解析往往导致了网站加载速度慢。现代浏览器针对这个问题开发了处理方式,它将域名缓存后,当用户点击其它页面地址后自动的获取


二、prefetch 连接网页预先加载

    当能确定网页在未来一定会使用到某个资源时,开发者可以让浏览器提前请求并且缓存好以供后续使用。prefetch支持预拉取图片、脚本或者任何可以被浏览器缓存的资源。

    <link rel="prefetch" href="image.png">

三、preconnect 

    和DNS prefetch类似,preconnect不光会解析DNS,还会建立TCP握手连接和TLS协议(如果需要)

    <link rel="preconnect" href="http://css-tricks.com">


http://www.alloyteam.com/2015/10/prefetching-preloading-prebrowsing/

打电话发短信写邮件怎么实现

一、打电话

    <a href="tel:0755-10086">打电话给:0755-10086</a>

二、发短信,winphone系统无效

    <a href="sms:10086">发短信给: 10086</a>

三、写邮件

    // 注: 在添加这些功能时,第一个功能以"?"开头,后面的以"&"开头

    1.普通邮件
    <a href="mailto:863139978@qq.com">点击我发邮件</a>

    2.收件地址后添加?cc=开头,可添加抄送地址(Android存在兼容问题)
    <a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net">点击我发邮件</a>

    3.跟着抄送地址后,写上&bcc=,可添加密件抄送地址(Android存在兼容问题)
    <a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net&bcc=384900096@qq.com">点击我发邮件</a>

    4.包含多个收件人、抄送、密件抄送人,用分号(;)隔开多个邮件人的地址
    <a href="mailto:863139978@qq.com;384900096@qq.com">点击我发邮件</a>

    5.包含主题,用?subject=
    <a href="mailto:863139978@qq.com?subject=邮件主题">点击我发邮件</a>

    6.包含内容,用?body=;如内容包含文本,使用%0A给文本换行 
    <a href="mailto:863139978@qq.com?body=邮件主题内容%0A腾讯诚信%0A期待您的到来">点击我发邮件</a>

    7.内容包含链接,含http(s)://等的文本自动转化为链接
    <a href="mailto:863139978@qq.com?body=http://www.baidu.com">点击我发邮件</a>

    8.内容包含图片(PC不支持)
    <a href="mailto:863139978@qq.com?body=<img src='images/1.jpg' />">点击我发邮件</a>

    9.完整示例
    <a href="mailto:863139978@qq.com;384900096@qq.com?cc=zhangqian0406@yeah.net&bcc=993233461@qq.com&subject=[邮件主题]&body=腾讯诚邀您参与%0A%0Ahttp://www.baidu.com%0A%0A<img src='images/1.jpg' />">点击我发邮件</a>

CSS样式

一、美化表单元素

    // 使用appearance改变webkit浏览器的默认外观
    input,select { -webkit-appearance:none; appearance: none; }

    // winphone下,使用伪元素改变表单元素默认外观
    1、禁用select默认箭头,::-ms-expand修改表单控件下拉箭头,设置隐藏并使用背景图片来修饰
            select::-ms-expand { display:none; }

    2、禁用radio和checkbox默认样式,::-ms-check修改表单复选框或单选框默认图标,设置隐藏并使用背景图片来修饰
            input[type=radio]::-ms-check,
            input[type=checkbox]::-ms-check { display:none; }

    3、禁用pc端表单输入框默认清除按钮,::-ms-clear修改清除按钮,设置隐藏并使用背景图片来修饰
            input[type=text]::-ms-clear,
            input[type=tel]::-ms-clear,
            input[type=number]::-ms-clear { display:none; }


二、其它实用的css

    1、去掉webkit的滚动条——display: none;
            // 其他参数
            ::-webkit-scrollba //滚动条整体部分
            ::-webkit-scrollbar-thumb   //滚动条内的小方块
            ::-webkit-scrollbar-track   //滚动条轨道
            ::-webkit-scrollbar-button  //滚动条轨道两端按钮
            ::-webkit-scrollbar-track-piece  //滚动条中间部分,内置轨道
            ::-webkit-scrollbar-corner       //边角,两个滚动条交汇处
            ::-webkit-resizer            //两个滚动条的交汇处上用于通过拖动调整元素大小的小控件

    2、禁止长按链接与图片弹出菜单
            a,img { -webkit-touch-callout: none }    

    3、禁止文字复制
            html,body {-webkit-user-select:none; user-select: none; }

    4、改变输入框placeholder的颜色值
            ::-webkit-input-placeholder { /* WebKit browsers */color: #999; }
            :-moz-placeholder { /* Mozilla Firefox 4 to 18 */color: #999; }
            ::-moz-placeholder { /* Mozilla Firefox 19+ */color: #999; }
            :-ms-input-placeholder { /* Internet Explorer 10+ */color: #999; }
            input:focus::-webkit-input-placeholder{ color:#999; }

    5、android上去掉语音输入按钮
            input::-webkit-input-speech-button {display: none}

    6、阻止windows Phone的默认触摸事件
            /*说明: winphone下默认触摸事件事件使用e.preventDefault是无效的,可通过样式来禁用,如: */
            html { -ms-touch-action:none; } //禁止winphone默认触摸事件

            取消input在ios下,输入的时候英文首字母的默认大写
            <input autocapitalize="off" autocorrect="off" />

    7、手机拍照和上传图片
            // IOS有拍照、录像、选取本地图片功能,部分Android只有选择本地图片功能。Winphone不支持
            <input type="file" accept="images/*" />
            <input type="file" accept="video/*" />

播放视频不全屏

<!--
        1.ios7+支持自动播放
        2.支持Airplay的设备(如: 音箱、Apple TV)播放
        x-webkit-airplay="true" 
        3.播放视频不全屏
        webkit-playsinline="true" 
-->
<video x-webkit-airplay="true" webkit-playsinline="true" preload="auto" autoplay src="http://"></video>

bug修改

android 2.3 bug
// 1.@-webkit-keyframes 需要以0%开始100%结束,0%的百分号不能去掉
// 2.after和before伪类无法使用动画animation
// 3.border-radius不支持%单位,如要兼容,可以给radius设置一下较大的值
// 4.translate百分比的写法和scale在一起会导致失效,例如: 
-webkit-transform: translate(-50%,-50%) scale(-0.5, 1)

android 4.x bug
// 1.三星 Galaxy S4中自带浏览器不支持border-radius缩写
// 2.同时设置border-radius和背景色的时候,背景色会溢出到圆角以外部分
// 3.部分手机(如三星),a链接支持鼠标:visited事件,也就是说链接访问后文字变为紫色
// 4.android无法同时播放多音频audio

一、消除transition闪屏
    .css {
        -webkit-transform-style: preserve-3d;
        -webkit-backface-visibility: hidden;
        -webkit-perspective: 1000;
    }

二、开启硬件加速

    //目前,像Chrome/Filefox/Safari/IE9+以及最新版本Opera都支持硬件加速,当检测到某个DOM元素应用了某些CSS规则时就会自动开启,从而解决页面闪白,保证动画流畅。
    .css {
        -webkit-transform: translate3d(0,0,0);
        -moz-transform: translate3d(0,0,0);
        -ms-transform: translate3d(0,0,0);
        transform: translate3d(0,0,0);
    }

三、渲染优化

    1、禁止使用iframe(阻塞父文档onload事件)

    2、禁止使用gif图片实现loading效果(降低CPU消耗,提升渲染性能)

    3、使用CSS3代码代替JS动画

    4、开启GPU加速

    5、使用base64位编码图片(不小图而言,大图不建议使用),以减少网络请求。比较耗费CPU。小图标优势在于: 减少HTTP请求、避免文件跨域、修改及时生效

—————————– 移动端的JS ——————————–

移动端touch事件(区分webkit和winphone)

一、当用户手指放在移动设备在屏幕上滑动会触发的touch事件

    1、以下支持webkit

        touchstart: 当手指触碰屏幕时候发生。不管当前有多少只手指
        touchmove: 当手指在屏幕上滑动时连续触发。通常我们再滑屏页面,会调用event的preventDefault()可以阻止默认情况的发生: 阻止页面滚动
        touchend: 当手指离开屏幕时触发
        touchcancel: 系统停止跟踪触摸时候会触发。例如在触摸过程中突然页面alert()一个提示框,此时会触发该事件,这个事件比较少用

    2、TouchEvent对象 : 

        touches: 屏幕上所有手指的信息
        targetTouches: 手指在目标区域的手指信息
        changedTouches: 最近一次触发该事件的手指信息
        touchend时,touches与targetTouches信息会被删除,changedTouches保存的最后一次的信息,最好用于计算手指信息

        event.changedTouches[0].clientX  获取移动端事件

    3、参数信息(changedTouches[0])

        clientX、clientY在显示区的坐标
        target: 当前元素

    4、事件响应顺序

        ontouchstart  > ontouchmove  > ontouchend > onclick

    5、以下支持winphone 8

        MSPointerDown: 当手指触碰屏幕时候发生。不管当前有多少只手指
        MSPointerMove: 当手指在屏幕上滑动时连续触发。通常我们再滑屏页面,会调用css的html{-ms-touch-action: none;}可以阻止默认情况的发生: 阻止页面滚动
        MSPointerUp: 当手指离开屏幕时触发


二、移动端的web页面click事件会产生200-300ms的延时响应

    移动设备上的web网页是有300ms延迟的,往往会造成按钮点击延迟甚至是点击失效。

    原因: 双击缩放是指用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。

            比如在点击一个<a href="#"></a>时,浏览器先捕获是单击还是双击缩放,所以捕获一次单击后,浏览器会hold一段时间来看是否有下一次点击,这个时间间隔就是300ms,这就是延时的由来,所以使用click来触发事件需要延时300ms后才生效

    解决方案: 
            fastclick可以解决在手机上点击事件的300ms延迟
            zepto的touch模块,tap事件也是为了解决在click的延迟问题

屏幕旋转的事件orientationchange

JS处理

    function orientInit(){
            var orientChk = document.documentElement.clientWidth > document.documentElement.clientHeight ? 'landscape' : 'portrait';
            if(orientChk =='lapdscape'){
                    //这里是横屏下需要执行的事件
            }
            else{
                    //这里是竖屏下需要执行的事件
            }
    }

    orientInit();
    window.addEventListener('onorientationchange' in window?'orientationchange':'resize', function(){
            setTimeout(orientInit, 100);
    },false)    


CSS处理

    // 竖屏时样式
    @media all and (orientation:portrait){   }

    // 横屏时样式
    @media all and (orientation:landscape){   }

audio元素和video元素在ios和andriod中无法自动播放

// 音频,写法一
<audio src="music/bg.mp3" autoplay loop controls>你的浏览器还不支持哦</audio>

// 音频,写法二
<audio controls="controls"> 
        <source src="music/bg.ogg" type="audio/ogg"></source>
        <source src="music/bg.mp3" type="audio/mpeg"></source>
        优先播放音乐bg.ogg,不支持在播放bg.mp3
</audio>

// JS绑定自动播放(操作window时,播放音乐)
$(window).one('touchstart', function(){
        music.play();
})

// 微信下兼容处理
document.addEventListener("WeixinJSBridgeReady", function () {
        music.play();
}, false);

// 小结
// 1.audio元素的autoplay属性在IOS及Android上无法使用,在PC端正常
// 2.audio元素没有设置controls时,在IOS及Android会占据空间大小,而在PC端Chrome是不会占据任何空间

重力感应事件

// 运用HTML5的deviceMotion,调用重力感应事件
if(window.DeviceMotionEvent){
        document.addEventListener('devicemotion', deviceMotionHandler, false)
}   

var speed = 30;
var x = y = z = lastX = lastY = lastZ = 0;
function deviceMotionHandler(event){
    var acceleration = event.accelerationIncludingGravity;
    x = acceleration.x;
    y = acceleration.y; 
    z = acceleration.z;
    if(Math.abs(x-lastX)>speed || Math.abs(y-lastY)>speed || Math.abs(z-lastZ)>speed ){
            //这里是摇动后要执行的方法 
            yaoAfter();
    }
    lastX = x;
    lastY = y;
    lastZ = z;
}

function yaoAfter(){
        //do something
}

设备判断

一、JS判断设备

    function deviceType(){
        var ua = navigator.userAgent;
        var agent = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];    
        for(var i=0; i<len,len = agent.length; i++){
            if(ua.indexOf(agent[i])>0){   
                return agent[i];     
                break;
            }
        }
    }
    deviceType();
    window.addEventListener('resize', function(){
        deviceType();
    })

二、JS判断微信浏览器

    function isWeixin(){
        var ua = navigator.userAgent.toLowerCase();
        if(ua.match(/MicroMessenger/i)=='micromessenger'){
            return true;
        }else{
            return false;
        }
    }

前端动画的几种方式

一、动画方式

    1、css3的transition 和 animattion

    2、定时器, 最原始的“window.setTimout()”或者“window.setInterval()” 不断更新元素的状态位置等来实现动画

    3、requestAnimationFrame方法

    4、canvas上作图来实现动画,也可以借助jQuery动画相关的API方便地实现

    5、SVG、WebGL

二、requestAnimationFrame  注意 Android不支持此方法

    requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘。

    设置这个API的目的是为了让各种网页动画效果(DOM动画、Canvas动画、SVG动画、WebGL动画)能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

    1、对requestAnimationFrame方法处理兼容:

        window.requestAnimFrame = (function(){
        return  window.requestAnimationFrame ||
                        window.webkitRequestAnimationFrame ||
                        window.mozRequestAnimationFrame ||
                        window.oRequestAnimationFrame ||
                        window.msRequestAnimationFrame ||
                        function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element){
                                window.setTimeout(callback, 1000 / 60);
                        };
        })();

    2、Example

        <div id="demo" style="position:absolute; width:100px; height:100px; background:#ccc; left:0; top:0;"></div>
        <script>
                var demo = document.getElementById('demo');
                function render(){
                        demo.style.left = parseInt(demo.style.left) + 1 + 'px'; //每一帧向右移动1px
                }
                var requestID = requestAnimationFrame(function(){
                        render();
                        //当超过300px后才停止
                        if(parseInt(demo.style.left) <= 300) {
                                requestAnimationFrame(arguments.callee);        // arguments.callee调用函数本身,或者给函数一个名,参数传个名
                        }
                });

                // cancelAnimationFrame(requestID);      // 停止动画重绘
        </script>

三、常用动画库

    Ani.js -- 基于CSS动画的生命处理库
    Dynamics.js -- 创建具有物理运动效果动画的js库
    Animate.css -- 齐全的CSS3动画库
    Three.js -- 让用户通过javascript入手进入搭建webgl项目的类库

    http://www.tuicool.com/articles/uUfYry
    http://www.jianshu.com/p/280e0ef90b96

其它API

一、querySelector()、querySelectorAll()

    获取元素 document.querySelector('#app');

二、window.devicePixelRatio 获取设备像素比,也叫做dpr

    这个属性是系统自动算出来的值返回给window.devicePixelRatio,公式就是

    // 比如ipone6 750px物理像素 / 375px设备像素,所以dpr为2,有这个属性不用我们就不用去算
    window.devicePixelRatio = 物理像素 / 设备独立像素;

三、getBoundingClientRect  js判断可视区域

    var htmlWidth = document.documentElement.getBoundingClientRect().width;     // html文档的宽度
    var top = document.documentElement.getBoundingClientRect().top;      // 元素顶端到可见区域顶端的距离
    var se = document.documentElement.clientHeight; // 浏览器可见区域高度。

四、document.documentElement、document.body

    document.body 获取body文档
    document.documentElement 获取HTML整个文档,从<!DOCTYPE html>开始

五、document.documentElement.getBoundingClientRect().width   获取html文档宽度

    获取文档可视区宽度

    问题
            document.body.clientWidth;   // 这里取的是body的宽度,如果body的宽度被改变
            window.innerWidth;      // 这里获取的是整个宽口的宽度,包括滚动条

    解决方法: document.documentElement.getBoundingClientRect().width

fetch 新一代ajax

一、fetch的请求设置与响应

    fetch('/some/url', {
        method: 'get'
    })
    .then(function(response) {
        // 成功
    })
    .catch(function(err) {
        // 出错了;等价于 then 的第二个参数,但这样更好用更直观 :(
    });


二、设置Header头

    fetch('https://www.baidu.com/search/error.html', {
        method: 'POST',
        headers: new Headers({
                'Content-Type': 'application/x-www-form-urlencoded'     // 指定提交方式为表单提交
        }),
        body: new URLSearchParams([["foo", 1],["bar", 2]]).toString()
    })
    .then((res)=>{
        return res.text()
    })
    .then((res)=>{
        console.log(res)
    })

fetch没有拦截请求和响应数据的功能,在单页面路由跳转时会需要提前去查看用户的一些登录信息,这时候需要使用Axios插件

问题收集

一、keydown侦听输入个数时,中文输入法输入个数的问题 

        let username = document.querySelector('#username');

        // 如果输入中文,输入法比如输 "物品" 五笔需要输入 "trkk",这样size为4,这样对中文判断长度会有问题
        $('#username').on('keydown', function(){
                let size = $(this).val().length;
                console.log(size);    
        })

        // 解决方法,侦听compositionend事件,返回的size正常
        $('#username').on('compositionend', function(){
                let size = $(this).val().length;
                console.log(size);  
        })

        http://www.alloyteam.com/2017/03/moves-the-input-box-fill-series-a/
        http://www.alloyteam.com/2016/12/alloytouch-full-screen-scroll-plugin-released-30-seconds-to-get-smooth-page-h5/


二、Retina屏1px边框处理

    高清屏,1px实际是2x2个像素来渲染,有的还是3x3,所以border: 1px 移动端会渲染为2px或3px

    <div class="bor-box">
            <div class="bor-querymidea">通过伪类创建边框,在通过媒体查询来适配</div>
    </div>

    解决方法

    1、通过-webkit-min-device-pixel-ratio 来确定两倍屏来修改边框大小

            .bor-querymidea{
                border: 1px #ccc solid;
            }

            /* 2倍屏 */
            @media only screen and (-webkit-min-device-pixel-ratio: 2.0){
                .bor-querymidea{
                    /* border: 0.5 #ccc solid;   retina屏是不识别0.5px,会解释为0 */
                    -webkit-transform: scaleY(0.5);
                    transform: scaleY(0.5);
                }
            }

            /* 3倍屏 */
            @media only screen and (-webkit-min-device-pixel-ratio: 3.0){
                .bor-querymidea{
                    -webkit-transform: scaleY(0.33);
                    transform: scaleY(0.33);
                }
            }

        2、js判断如果devicePixelRation的值

            devicePixelRation = 2; 输出viewport: <meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">

            devicePixelRatio = 3; 输出 <meta name="viewport" content="initial-scale=0.333, maximum-scale=0.333, minimum-scale=0.333, user-scalable=no">

        https://www.jianshu.com/p/7e63f5a32636          // 7咱方法


三、设置viewport 缩放比例

    (function(doc, win) {
        var scale = 1.0;
        if (win.devicePixelRatio === 2) {
            scale *= 0.5;
        }
        if (win.devicePixelRatio === 3) {
            scale *= 0.333333;
        }
        var text = '<meta name="viewport" content="initial-scale=' + scale + ', maximum-scale=' + scale +', minimum-scale=' + scale + ', width=device-width, user-scalable=no" />';
        doc.write(text);       
    })(document, window);

    https://www.cnblogs.com/stella1024/p/7199832.html

收集工具

1、browsersync 多端浏览器同步测试工具  http://www.browsersync.cn/

2、lib-flexible 处理根据屏幕的尺寸将Html中的font-size的值自动转换  https://github.com/amfe/lib-flexible

3、sublime的px转rem的插件   https://github.com/flashlizi/cssrem

| http://www.uigreat.com/page/guifan // 移动端屏幕尺寸集合
| http://cubic-bezier.com/#.55,.01,.38,.99 // 调节css3动画效果并导出代码
| https://segmentfault.com/a/1190000007075834 // Retina屏
| http://mp.weixin.qq.com/s?__biz=MzAwNjI5MTYyMw==&mid=404009356&idx=1&sn=e3218b95b78a5f043e7b0e3df49703d3&scene=4#wechat_redirect
| http://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html
| http://www.alloyteam.com/2016/03/mobile-web-adaptation-tool-rem/#prettyPhoto rem
| https://github.com/amfe/article/issues/17 // 淘宝H5终端适配

深入理解CSS3

| 选择器
| 文字样式: text-shadow、word-break、word-wrap、font-face、wrod-spacing、letter-spacing、text-overflow
| 盒模型: calc计算属性值、box-sizing元素的宽高是否包括padding、border的值、box-shadow、box-reflect、resize
| 布局: dispay:flex布局、dispay:box 弹性盒模型
| 分栏布局: column-width、column-count、column-gap、column-rule
| 背景: background-clip、background-size
| 变形: transform: scale、skew、translate、rotate、matrix,transform-origin
| 动画: transition: transition-property、transition-duration、transition-timing-function、transition-delay,animation

选择器

一、基本选择器

    1、 * 通配符: 用于html的所有结点 -> * { width:200px; }

    2、 元素选择器: 页面的元素 -> li { border:1px #fff solid; }

    3、 类选择器: 所有指定的类别 -> .cla { width:200px; height:30px; }

    4、 id选择器: #k0 { background-color:#000; }

    5、 m n{} 后代选择器: .nav li { width:200px; }    // .nav下的所有li元素

    6、 m > n 子选择器: ie6不支持 -> .nav > li { width:200px; }    // 只匹配.nav下的子li元素,孙li不匹配

    7、 m + n 相邻选择器: ie6不支持 -> .nav + div { background-color:#ccc; }    // 匹配.nav相邻的div元素

    8、 m ~ n 兄弟选择器: ie6不支持 -> .nav ~ li { background-color:#ccc; }    // 与.nav所有的同辈元素

    9、 m, m, m 群组选择器: .nav1, .nav2, .nav3 { width: 2000px; }    // 群组选择器将每个选择器用","号分开


二、属性选择器

    1、[attr]: 指定属性名

    2、[attr==val]: 指定属性等于匹配

    3、[attr*=val]: 匹配属性具有attr并且包含val指定值

    4、[attr^=val]: 匹配指定属性的值,以val开头

    5、[attr$=val]: 匹配指定属性的值,以val结尾        如果id="abc-1",匹配[attr $= \-1]使用转义\


三、元素

    1、:first-line: 为某个元素第一行文字的使用样式

    2、:first-letter: 用于首字母

    3、:before: 用于在某个元素之前插入一些内容,如: 元素:before { content: "插入的文字" };

    4、:after: 用于在某个元素之后插入一些内容,如: 元素:after{ content: "插入的文字" };

    5、:root: 选择器将样式绑定到页面的根元素中,根元素是指位于文档树中最顶层结构的元素.

    6、:not: 对某个结构元素使用样式,但排除这个结构元素下面子结构元素,让它不使用这个样式可以使用not。

    7、:empty: 指定元素为空白时使用的样式

    8、:target: 

    9、:first-child: 指定元素中第一个子元素

    10、:last-child: 指定元素中的最后一个子元素

    11、:nth-child(3): 指定元素中的第3个元素.   li:nth-child(3) { background: yello; }   可以指定even奇数、odd偶数

    12、:nth-last-child(3): 指定元素中从后数第3个元素

    13、:nth-of-type: 找标签下指定的第几个子元素,例: .box p:nth-of-type(2): 找出个box下的第二个p元素

    14、:nth-last-of-type(): 从后找

    15、:only-child: 父元素中只有一个子元素.

        *** nth-child与nth-of-type的区别 *** 

        nth-child 从子元素的第一个开始无论不会指定元素
        nth-of-type 所有子元素的序列,而不是指定某一元素下查找

        <style>
            body { margin: 0; }
            .box li:nth-child(2) { background-color: #ccc; }         // 影响 <li>bbb</li>
            .box li:nth-of-type(2) { background-color: #ccc; }         // 只对子元素li的第2个 影响 <li>ccc</li>
        </style>

        <div class="box">
            <ul>
                <p>aaa</p>
                <li>bbb</li>
                <li>ccc</li>
                <li>ddd</li>
            </ul>
        </div>


四、伪类选择器

    什么是伪类选择器: 使用类选择器把相同元素定义成不同样式,如

        p.right { text-align: right; }
        p.left {text-align: lef; }

    1、E:hover: 当鼠标指针移动到元素上所使用样式

    2、E:active: 用来指定元素被激活(鼠标在元素上按下还没有松开)时使用样式

    3、E:focus: 元素获得光标时使用

    4、E:enabled: 元素可用时状态使用

    5、E:disabled: 元素不可用状态时样式

    6、E:read-only: 元素只处于只读状态下时使用

    7、E:read-write: 元素处于非只读状态时使用

    8、E:checked: 指定单选或多选

    9、E:default: 用来指定当页面打开时默认处于选取状态的单选或多选框

    10、E:indeterminate: 用来指定页面打开时,一组单选中任何一个单选框都没有设定为选取状态.

    11、E::selection: 用来指定当元素处于选中状态时的样式

    12、E:target: 显示的两条

    13、~: 兄弟元素选择器

伪类与伪元素

伪类 - 用于已有元素处于某个状态,为其添加对应的样式,比如用户悬停 通过 :hover

伪元素 - 用于创建一些不在文档树中的元素,并为其添加样式,如 :before来在一个元素前增加一些文本

一、伪类 用于向某些选择器添加特殊效果

    a:link: 未被访问过
    a:visited: 已经被访问的链接
    a:hover: 鼠标指针移动到的链接
    a:active: 被点击的链接
    :first-chidle: 向元素的第一个子元素添加样式


二、伪类元素 用于向某些选择器添加特殊效果

    ::first-letter: 设置第一个字符的样式属性

    ::first-line: 设置第一行的样式

    ::before 和 ::after: 用于在元素前和元素后配置content属性添加内容

        .box::before { content: '这里是在box元素之前显示'}
        .box::after { content: '这里是在box元素之后显示' }


三、css3规则伪类使用一个":", 伪元素使用两个"::"

    : 用于css2的伪类,:: 用于css3的伪类

伪类
伪元素

文字样式

一、text-shadow: 文字阴影  text-shadow: 横向 纵向 模糊半径 颜色

    多阴影: text-shadow: 10px 10px 2px #ccc, 20px 20px 3px #c3c3c3; 以逗号分割.


二、word-break: 文字自动换行

    normal: 使用浏览器的默认行为

    keep-all: 只能在半角空格或连接符处换行

    break-all: 允许在单词内换行


三、word-wrap: 长单词与URL地址自动换行

    normal: 浏览器默认,只有在半角空格或连接符处换行

    break-word: 长单词或URL地址内进行换行


四、@font-face: 服务器端字体

    @font-face {
        font-family: 'iconfont';
        src: url('iconfont.eot');                 /* IE9 */
        src: url('iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
        url('iconfont.woff') format('woff'),     /* chrome、firefox */
        url('iconfont.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
        url('iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
    }

    // 使用字体
    .iconfont{ font-family:"iconfont"; font-size:16px;font-style:nrmal; }


五、word-spacing: 设置单词字段间距, 修复 IE6、7 中始终存在的 1px 空隙,减少单词间的空白(即字间隔)

    .main{
        font-size:0;
        *word-spacing:-1px;
    }

六、letter-spacing: normal;  /* 设置字母、字间距为0 */ 

七、text-overflow: 溢出的文本末尾加省略标记

    clip: 不显示省略号

    ellipsis: 文字溢出时显示 ...

    ellipsis-word: 

盒模型

一、display: 定义盒类型

    block: 转成块元素

    inline: 转成内联元素

    inline-block: 属于block的一种,也具有inline的特点

    inline-table: 

    flex、inline-flex: flex弹性布局

    box、inline-box: box弹性盒模型,父元素上加此属性


二、box-sizing: 指定元素的宽与高度的计算方法

    1、content-box: border和padding不计算width之内(标准盒模型)

    2、border-box: border和padding计算入width之内,元素的宽高 = border + padding + content + width/height

    3、padding-box: padding计算入内(怪异盒模型)

    好处: 如果我设置两列都为50%,如果之前我加入了边距,加了内边距等,这个百分比计算就不好撑控了,

         所以有了box-sizing就可以不用管内边距的值是多少边框值是多少,最后都为50%

    -webkit-box-sizing、-moz-box-sizing、box-sizing


三、calc 给属性的值做计算

    Android不支持

    例: height: calc(100% - 80px);

    rule:

        使用“+”、“-”、“*” 和 “/”四则运算;
        可以使用百分比、px、em、rem等单位;
        可以混合使用各种单位进行计算;
        表达式中有“+”和“-”时,其前后必须要有空格,如"width: calc(12%+5em)"这种没有空格的写法是错误的;
        表达式中有“*”和“/”时,其前后可以没有空格,但建议留有空格。


四、盒相关属性

    1、box-shadow: 盒阴影    box-shadow: 横向距离 纵向距离 模糊半径 颜色 inset(内阴影)

    2、box-reflect: 倒影 

        box-reflect: 方向 距离 渐变

            方向: above: 倒影在上边     below: 倒影在下边     left: 倒影在左边         right: 倒影在右边

        Example: -webkit-box-reflect: below   0   -webkit-linear-gradient(transparent,transparent 50%,rgba(255,255,255,.3));

    3、resize: 自由绽放, 可以使用当前元素用鼠标进行宽度的缩放

        both: 水平垂直都可以缩放

        horizontal: 水平方向可以缩放

        vertical: 垂直都可以缩放

        注意: 一定要加overflow: auto 才可以缩放

Flex 布局

布局分类: 1、静态 px        2、流式 fluid        3、自适应(弹性布局)flex        4、响应式 responsive

    box-sizing是先出来的,flexbox是过渡版,flex最新语法,一个特性是flex没有的,文字可以垂直居中

    .box{
        display: -webkit-flex; /* Safari/Chrom */
        display: flex;
    }


任何一个容器都可以设置flex布局  # 父元素设置display: flex;  行内元素设置 display: inline-flex;    

display: flex 或 inline-flex;   // 注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。

一、父容器上设置的属性: 

    1、flex-direction: 子元素的排列方向

        row 水平方向,起点在左端 | row-reverse 水平方向,起点在右端 | column 垂直方向,起点在上沿 | column-reverse 垂直方向,起点在下沿

    2、flex-wrap: 是否换行显示  nowrap 不换行 | wrap 换行第一行在上方 | wrap-reverse 换行,第一行在下方        

    3、flex-flow: flex-direction属性 和 flex-wrap

    4、justify-content: 子元素的对齐方式 

        flex-start 左对齐 | flex-end 右对齐 | center 居中 | space-between 两端对齐 | space-around 每个项目两侧间隔相等

    5、align-items: 主轴对齐方式,指定伸缩项目沿主轴对齐方式 (水平方向)

        flex-start 交叉轴的起点对齐。

        flex-end 交叉轴的终点对齐。

        center 交叉轴的中点对齐。

        baseline 项目的第一行文字的基线对齐。

        stretch(默认值)如果项目未设置高度或设为auto,将占满整个容器的高度。

    6、align-content: 侧轴对齐方式,指定伸缩项目沿着侧轴对齐方式 (垂直方向)


二、栏目的属性

    1、order: 栏目排列顺序。数值越小,排列越靠前,默认为0

    2、flex-grow: 放大比例,默认为0,即如果存在剩余空间,也不放大。

    3、flex-shrink: 项目的缩小比例

    4、flex-basis: 项目占据的主轴空间

    5、flex: 设置列所在容器的比例

            flex: 1,相当于flex: 1 1 auto, 如果想指定一个列的宽度,flex: 0 0 100px;

            .boxA { flex:1 } .boxB{ flex: 2 }

    6、align-flex: 允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。

    7、align-self: 指定多行伸缩容器的对齐,可以单独伸缩子元素,会覆盖align-items


Example:

    .row{width:200px;
        height: 50px;
        /*加上厂商前缀,目前使用方式都有三种写法: 1,旧的2,过度的3,新的*/
        display: -webkit-box;
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
        -webkit-flex-flow: row nowrap;
        -ms-flex-flow: row nowrap;
        flex-flow: row nowrap;}

    .row div{ 
        width:50px;height:50px;
        -webkit-box-flex: 1; 
        -webkit-flex: 1; 
        -ms-flex: 1;
        flex: 1; 
        text-align: center;
        line-height: 5rem;
        background-color: #f69f75;
    }

https://github.com/ccforward/cc/issues/60
http://www.alloyteam.com/2015/05/xi-shuo-flexbox-dan-xing-he-zi-bu-ju/

box弹性盒模型

一、display: box 父元素加值

    display中加 box 或 inline-box: 使用弹性盒模型时使用

    box-orient: 定义盒模型的布局方向  horizontal 水平显示  vertical 垂直显示

    box-direction: 元素排列顺序  normal 正序   reverse 倒序

    box-ordinal-group: 设置元素的具体位置 

        .box div:nth-of-type(1){ --webkit-box-ordinal-group: 2 }    // 将第一个元素放到第二个位置显示 

二、box-flex: 定义盒子的弹性空间

    .boxB div { height: 100px; background-color: red; border: 1px #fff solid;}
    .boxB div:nth-of-type(1){ -webkit-box-flex: 1; }        // 这里可以写固定宽度
    .boxB div:nth-of-type(2){ -webkit-box-flex: 2; }
    .boxB div:nth-of-type(3){ -webkit-box-flex: 3; }
    .boxB div:nth-of-type(4){ -webkit-box-flex: 4; }
    .boxB div:nth-of-type(5){ -webkit-box-flex: 5; }

三、box-pack: 对盒子富裕空间管理,让盒子左侧、右侧还是居中显示,相当于float:left right

    star: 所有子元素在盒左侧显示,富余空间在右侧

    end: 所有子元素在盒右侧显示,富余空间在左侧

    center: 所有子元素居中

    justify: 富余空间在子元素之间平均分布

四、box-align: 垂直方向对元素的位置进行管理

    start: 所有元素居顶

    end: 所有元素居底

    center: 所有元素居中

分栏布局

给要分栏内容的父级上加入下面属性对文字进行分栏显示

1、column-width: 栏目宽度

2、column-count: 栏目列数

3、column-gap: 栏目距离

4、column-rule: 栏目间隔线

mask蒙版

#box {
    width: 100%;
    height: 300px;
    background: url(../img/eric.jpg) no-repeat;
       -webkit-mask-repeat: no-repeat;
}

.mask_img_1 {
    -webkit-mask-box-image: url(../img/apple.png) 10 20 30 40 round round;
}

1、mask-box-image: 定义图片遮罩

2、mask-composite: 定义同一个元素上有多个图片遮罩的顺序

3、mask-clip: 定义图片遮罩延伸的位置

4、mask-repeat: 定义遮罩是否重复

5、mask-size: 定义遮罩的大小    

渐变

一、linear-gradient: 线性渐变

    background: -webkit-linear-gradient(top, #000 0%, #fff 100%);  // (起始位置, 开始颜色 占多少比例, 结束颜色  占多少比例) 

    1、起始位置可以写成 (top left) 从左上开始,也可以写成angle 角度值 45deg, background: -webkit-linear-gradient(45deg, #ccc 50%, #000 50%);

    2、(left top, #ccc 50%, #000 50%) - 写成50%百分比两个颜色没有过渡,如果成写100px两个颜色有过渡色

    简写: background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #000), color-stop(100%, #fff));

二、radial-gradient: 径向渐变

三、color-stop(透明度, reg): 从一个颜色到另一个颜色的渐变,需要color-stop

http://www.zhangxinxu.com/wordpress/2013/09/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3css3-gradient%E6%96%9C%E5%90%91%E7%BA%BF%E6%80%A7%E6%B8%90%E5%8F%98/

背景和边框

背景: 
    1、background-clip: 指定背影的范围

        border-box 背景图以边框线为开始     padding-box 背景图已padding以开始    content-box 背景以内容为开始    text 文字中嵌背景图,文字外没有背景图

    2、background-origin: 绘制背影图像起点

        border-box 以边框线为起点    padding-box 以padding为起点     content-box  以内容区为起点

    3、background-size: 指定背影图像的尺寸

        auto: 背景图真实的大小

        cover:背景图像缩放,保留图像原有的比例/长宽比,不管背景图像大于还是小于背景区域,都会覆盖背景区域,图像的宽度或高度等于或超过背景区域,再次,根据背景图像的比例是否匹配的背景区域,背景图像的某些部分可能不在背景区域内。

        contain:背景图像缩放,同时保留图像原有的比例/长宽比,无论是图像的宽度或高度超过背景区域,以尽可能大的覆盖背景区域。因此,根据背景图像的比例是否匹配背景区域,可能会有一些背景图像覆盖不到背景地区。

        指定值: background-size: 100px 200px;  or    background-size: 50% 80%;

    4、background-break: 指定内联元素的背景平时循环方式

边框: 
    1、border-radius[ˈreɪdiəs]: 圆角的半径

    2、border-image: 图像边框

transform 2D

一、transform分类: 

    1、缩放: scale(0.5) 0-1之间  transform: scale(0.5)

    2、倾斜: skew实现文字或图像的倾斜  transform: skew(30deg, 30deg)

    3、移动: translate移动元素  transform: translate(50px, 50px;)

    4、旋转: rotate[ˈroʊteɪt]旋转元素  transform: rotate(45deg)

    5、矩阵: matrix


二、旋转基准点: 

    transform-origin: left top;     以左上为基础点

transform 3D

一、transform-style: 指定3D空间呈现,主要有两个属性值: flat 和 preserve-3d。

    1、flat: 值为默认值,表示所有子元素在2D平面呈现

    2、preserve-3d: 表示所有子元素在3D空间中呈现

        2)perspective: 景深

        3)perspective-origin: 景深基点

        4)backface-visibility: 隐藏背面

        5)Transform中的3D: 

二、perspective [pəˈspektɪv]: 200; 景深的远近,数越小景深越明显

三、perspective-origin: 50% 50%;   景深基点, 中间

四、backface-visibility: hidden 隐藏背面

五、3D元素

    1、translateX、translateY、translateZ

    2、rotateX、rotateY、rotateZ

    transform: translate3d(x, y, z)


Example:

    <style>
        .container {
            /* 告诉引擎使用的是3D */
            -webkit-transform-style: -webkit-preserve-3d;

            /* 设置景深和景深基点 */
            -webkit-perspective: 200;
            -webkit-erspective-origin: 50% 50%;
        }

        .boxA {
            width: 200px;
            height: 200px;
            margin: 100px auto;
            background-color: #7cb305;

            transform: rotateX(45deg);
        }
    </style>

    <div class="container">
        <div class="boxA"></div>
    </div>


https://www.qianduan.net/high-performance-css3-animations/
https://segmentfault.com/a/1190000005071819

css开启硬件加速

大多数电脑的显卡都支持硬件加速、可以发挥GPU的力量,CSS animations, transforms 以及 transitions 不会自动开启GPU加速,而是由浏览器的缓慢的软件渲染引擎来执行

一、开启硬件加速

    将元素转成3D变化就可以来欺骗浏览器开启硬件加速

    .cube {
        -webkit-transform: translate3d(0, 0, 0);
        -moz-transform: translate3d(0, 0, 0);
        -ms-transform: translate3d(0, 0, 0);
        transform: translate3d(0, 0, 0);
    }

二、解决使用transform或animator时页面闪烁的问题

    .cube {
        -webkit-backface-visibility: hidden;
        -moz-backface-visibility: hidden;
        -ms-backface-visibility: hidden;
        backface-visibility: hidden;

        -webkit-perspective: 1000;
        -moz-perspective: 1000;
        -ms-perspective: 1000;
        perspective: 1000;
    }

CSS3动画

一、transition 允许块级元素属性,在指定时间内平滑改变

    transition: 过渡属性名  过渡时间  过渡模式  延迟时间

    .box { transition: all 2s linear 3s; }

        transition-property: all;     // 设置过渡效果,all或指定一个css属性; 如果是all就是所有属性只要有变化的就执行过渡效果

        transition-duration: 2s;     // 动画完成的时间

        transition-timing-function: // 过渡模式

        transition-delay: 2s;         // 延迟时间

    # 多个过渡通过逗号分割 .box { transition: width 2s linear, height 3s linear 2s; }

    # transition事件: 

        obj.addEventListener('transitionend', function(){}, false);
        obj.addEventListener('WebkitTransitionend', function(){}, false);

    过渡模式: ease、linear、ease-in、ease-out、ease-in-out

二、animation: 能够在样式中创建多个关键帧来编写样式

    1、按百分比来做不同的样式处理

        @-webkit-keyframes myColor {
            0%{
                background-color: red;
            }
            50%{
                background-color: yellow;
            }
            100%{
                background-color: red;
            }
        }

        .box { animation: myColor 5s linear; }

三、from...to,从0%到100%

    animation: inpEffect .4s linear;

    @-webkit-keyframes inpEffect {
        from { top:0px; }
        to { top:200px; }
    }

四、将animation动画执行到100%后停住,animation-fill-mode: forwards;  

    animation: inpEffect .4s linear;        // 或者加到animation中 animation: inpEffect .4s linear forwards;
    animation-fill-mode: forwards;

    @-webkit-keyframes inpEffect {
        to {
            transform: scaleX(1); 
        }
    }

兼容前缀

    -webkit-: 指对chrome这种webkit内核的浏览器

    -moz-: 指对Firefox浏览器

    -o-: 指对Opera浏览器

Media Queries 查询媒体

一、<meta>标签

    <meta name="viewport" content="width=device-width; initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    1、width=device-width: 宽度等于设备宽度

    2、initial-scale: 初始缩放比例   initial[ɪˈnɪʃəl]

    3、minimum-scale、maximum-scale: 允许用户缩放最小、大比例

    4、user-scalable: 是否允许用户缩放


二、css定定义

    媒体查询: @media 设备类型 and (设备特性) { 样式代码 }

    1、设备类型: 

        1) all 所有媒体
        2) braille 盲文触觉设备
        3) embossed 盲文打印机
        4) print 手持设备
        5) projection 打印预览
        6) screen 彩屏设备
        7) speech '听觉'类似的媒体类型
        8) tty 不适用像素的设备
        9) tv 电视

    2、and | not | only

    3、min-width、max-width 最小、大宽度

    4、device-width、device-height: 设备屏幕的宽、高度。 device[dɪˈvaɪs]

    引用不同样式: 

        @media screen and (mim-width:480px){    // 窗口宽高大于480时调用下面样式
            .ads {
                display:none;
            }
        }

        @media screen and (min-width: 500px) and (max-width: 800px){    // 窗口宽度500-800之间执行下面样式
            .ads {
                display:none;
            }
        }

三、引用样式文件表

    引用不同样式表 <link rel="stylesheet" type="text/css" href="a.css" meida="screen and (min-width: 800px)">

css性能

一、尽可能少使用box-shadows与gradients,投影和渐变都是性能杀手

二、将动画元素不在文档流中,以减少重排,使用

    position: fixed;  
    position: absolute;

| https://segmentfault.com/a/1190000006878700
| http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool flex布局
| http://www.ruanyifeng.com/blog/2015/07/flex-examples.html
| http://www.cnblogs.com/module/p/5578533.html
| https://isux.tencent.com/css3/tools.html // 动画工具生成代码
|
| https://github.com/zhiqiang21/blog/issues/2
| http://div.io/topic/1348
| https://github.com/tj?page=2&tab=repositories
| http://www.alloyteam.com/2016/05/summary-of-pseudo-classes-and-pseudo-elements/ 伪类、伪元素
| https://zhuanlan.zhihu.com/p/33984503 // z-index
| https://cases.aotu.io/ h5活动案例
| https://zhuanlan.zhihu.com/p/25070186 // 布局
| https://zhuanlan.zhihu.com/p/25068655 // 居中布局

DOM

DOM介绍

DOM 文档对象模型     D - Document      O - Object      M - Model

Node 对象属性

1、nodeType: 节点类型

    e.target.nodeType 来获取节点的类别

    1、Element 1

    2、Attr  2

    3、Text  3

    4、注释  8

    5、Document 9


2、nodeName: 节点名称   返回的是大写 'DIV'

3、nodeValue: 节点的类型

    元素节点的 nodeValue 是 undefined 或 null
    文本节点的 nodeValue 是文本本身
    属性节点的 nodeValue 是属性值

    <p>dfsdfsdf</p>

    let oP = document.querySelector('p');   
    // 这里注意oP是元素如果直接写成oP.nodeValue返回是null,写成oP下的第一个节点才找到文本元素
    oP.firstChild.nodeValue;            

4、parentNode: 返回当前节点的父节点   e.target.parentNode.nodeName

    document.querySelector('ul').parentNode     // <div class="box">...</box>

5、childNodes、children: 返回所有子节点元素,不包括孙节点

    <ul id="list">
        <li>111</li>
        <li>222</li>
        <li>
            <ul>
                <li>333</li>
                <li>444</li>
            </ul>
        </li>
    </ul>

    let oList = document.querySelector("#list");
    let lis = oList.children;
    for(let i=0; i<lis.length; i++){
        console.log(lis[i].nodeName);   // output LI LI LI
    }

    ** childeNodes与children区别 ** 

        childeNodes: 包括空行的文本节点, 如果是空行的节点返回是一个text节点
        children: 不包括空行之类的节点

6、hasChildNodes(): 判断是否有子节点,返回Booleanw值

7、firstChild、lastChild: 返回子节点的第一个节点、最后一个节点

    firstChild 相当于 children[0]

    lastChilde 相当于 children[node.children.length-1]

    <div id="car"><p>aaa</p><div>bbb</div><span>ccc</span></div>

    let oCars = document.querySelector("#car");
    console.log(oCars.firstNode, oCars.lastNode);   //<p>aaa</p> 、 <span>ccc</span>

8、previousSibling、nextSibling: 当前节点的前一个节点、后一个节点

    注意: 如果是空行返回的是 text

9、innerHTML: 获取或修改HTML元素内容

    Element.innerHTML = '<div>xxxxx<div>';

10、innerText: 获取或修改的是除去html的文本

11、outerHTML、outerText: 与innerHTML、innerText相当,不同的是它包含当前节点元素,inner只包含子节点元素

12、offsetParent: 获取当前元素定位的父元素  找到基于设置position的父元素

     document.querySelector('ul').offsetParent

Node 对象的方法

一、节点操作方法

    1、getElementById(): 获取指定ID的元素

    2、getElementsByTagName(): 获取指定标签名称的所有元素

    3、getElementsByClassName(): 获取指定类名的元素

    4、appendChild(): 追加子节点  注意这里插入的是一个节点,而不是HTML的字符串 parent.appendChild(children);

    5、removeChild(): 删除子节点,不能删除孙子节点    (removeNode 只支持IE)

        删除节点 并返回删除的节点
        let oSubCar = document.querSelector('#subCar');
        document.querySelector('body').removeChild(oSubCar);        // <div id="subCar">...</div>

    6、cloneNode(Boolean): 复制节点  如果参数为true复制指定节点下包括所有子节点,如果不写只复制当前节点不手包子节点

        <div class="car">
            <ul id="box">
                <li>aaa</li>
                <li>bbb</li>
                <li>ccc</li>
            </ul>
        </div>
        <div id="subCar"></div>

        <script>
            // 将id=box所有的节点插入到id=subCar中
            let boxList = document.querySelector('#box').cloneNode(true);
            var oSubCar = document.querySelector('#subCar');
            oSubCar.appendChild(boxList);
        </script>

    7、hasAttributes(): 判断当前节点是否拥有属性

        <div id="miniCar"></div>
        <div>swsss</div>

        let isAttribute = document.getElementsByTagName('div')[1].hasAttributes();
        console.log(isAttribute);   // false

    8、hasChildNodes(): 判断当前节点是否拥有子节点

    9、insertBefore(newitem, ex): 在指定节点之前插入

        insertAfter(): 这个需要自己来写没有这个方法

        let oMain = document.querySelector('#main');
        let oP = document.querySelector('p');
        let oUl = document.querySelector('.uls').cloneNode(true);
        oMain.insertBefore(oUl, oP);    将ul元素内所有节点复制并插入到oP元素之前

    10、replaceChild(newNode, oldNode): 替换节点

        document.querySelector('body').replaceChild(oMiniCar, oSubCar)


二、创建元素方法

    1、createAttribute(): 创建属性节点

    2、createElement(): 创建元素节点

    3、createTextNode(): 创建文本节点


三、操作属性方法

    1、getAttribute(): 获取属性值

    2、setAttribute(): 设置属性值

CSS样式

1、style:获取或设置style值   Element.style.color = 'blue' 

2、currentStyle、getCurrentStyle()获取样式中每个属性的值

    var oBox = document.querySelector('#box');
    var getStyle = function(obj, attr){
        return window.getComputedStyle ? window.getComputedStyle(obj, null)[attr] : obj.currentStyle[attr];
    }

    var attrTxt = getStyle(oBox, 'width');          // '100px';

    注意: (1)中style只能获取元素中的内联样式,而currentStyle、getCurrentStyle()无论是内联样式还是在class中都可以找到

3、getComputedStyle(元素, 伪类): 获取指定元素值,currentStyle(ie独有) 

    <script>
        function getStyle(element, attr) {
            if(window.getComputedStyle) {
                return window.getComputedStyle(element, null)[attr];
            } else {
                return element.currentStyle[attr];
            }
        }

        // 获取class=position-node元素上的position值
        var dom = document.querySelector(".position-node");
        var style = getStyle(dom);
        console.log(style.position);    // 返回relative
    </script>


    *** element.getComputedStyle与element.style的区别

    element.getComputedStyle: 只读
    element.style: 可读写

4、className: 获取或设置元素的类名  Element.addClass = 'classname'

其它

1、write(): 向输出流写文本或html

2、document.title: 返回标题

4、"javascript:" : 伪协议 来调用javascript http协议(http://),FTP协议(ftp://)

5、对象检测: 可以测试浏览器是否支持当前对象

    if(document.getElementById){ ...}

性能

1、createDocumentFragment: 创建文档碎片

    Example: 创建节点并插入到body中,如果不使用文档碎片,每次都需要重新插入一次

    var oFragment = document.createDocumentFragment();
    for(var i = 0 ; i < 10; i ++) {
        var p = document.createElement("p");
        var oTxt = document.createTextNode("段落" + i);
        p.appendChild(oTxt);
        oFragment.appendChild(p);
    }
    document.body.appendChild(oFragment);

事件

1、表单事件:

    submit事件

    reset事件

    click事件

    change事件

    focus事件(不冒泡) (IE和ES5支持冒泡的focusin)

    blur事件(不冒泡) (IE和ES5支持冒泡的focusout)

    input事件(ES5 textinput提供更方便的获取输入文字的方案)


2、Window事件

    load: 资源全部加载完成后触发事件(图片、css、js)

    DOMContentLoaded事件: Document对象构建完后就开始调用此事件

    readyStatechage事件:

    unload事件: 关闭borwser的时候触发

    beforeunload事件

    resize: 浏览器窗口发生改变触发

    scroll: 滚动条有变化时触发


3、鼠标事件

    click: 点击事件

    dbclick:双击事件

    mouseover: 鼠标移入事件(冒泡)

    mouseout: 鼠标移出事件(冒泡)

    mousedown: 鼠标按下事件

    mouseup: 鼠标放开事件

    contextmenu: 上下文本菜单事件

    mouseenter: 事件(不冒泡)

    mouseleave: 事件(不冒泡)

    mousewheel: 事件(FF DOMMouseScroll事件、DOM3 wheel事件)


4、键盘事件

    keydown事件

    keyup事件

    keypress事件

正则表达式

特殊字符和转义序列

1、[...] 位于括号内的任意字符            

    /[abcde]/.test('aboot');     // 只要含有任意一个字符返回 true

    /a[bo]t/.test('abot');        // false 中间只能含有其中一个字符,匹配'abt'或'aot'

2、[^...] 不在括号中之中的任意字符

    /a[^bo]t/.test('ast');        // true a|t之间不含有b、o期中一个字符

*3、. 除了换行和Unicode行止符之外的任意字符

    /a.t/.test('a*t');        // true , 'a\nt'换行false,使用 \.来进行转义

4、\w 任何ASCII字符,等于[a-zA-Z0-9_]

    /\w/.test('think');        // true, 不含有其它字符

5、\W 任何非ASCII字符单字字符,等于[^a-zA-Z0-9_]

    /\w/.test('think');        // false, 至少需要有一个特殊字符

6、\s 任何空格

    /\s/.test('I think');    // true

7、\S 不包含空格

    /\s/.test('I think');    // false, 非空格为true

8、\d 任何数字,等于[0-9]

9、\D 除了数字之外的任意字符

10、\b 单词边界

    例: 匹配 hi 这个词,如果写成 /hi/ 这样 'wordhibiry are you' 也会匹配,如果加\b会单词的分界空格处来匹配, /hi\b/.test('word hi biry are you');  true

11、\B 非单词边界 

指定匹配的位置

1、^ 匹配字符串的开头

    /^ab/.test('absolute');        // true 以ab开头

2、$ 匹配字符串的结尾

    /te$/.test('absolute');        // true 以te结尾

* 3、? ! 一个反前向声明者,含义与反前向声明相反

选择、分组和引用

1、| 用于分隔选择的字符,相当于或

    /oa|on|op/.test('option');    // true,只要带有oa、on、op都匹配

2、(...) 分组,相当于并且

    /(\d+&)([a-zA-Z]+%)/.test('1234&abcde%');        // true, 必须包含数据+&,并且还包含英文字母+%

* 3、(?...) 只组合,把项组合到一个单元,但不记忆与该组匹配的字符

    (?:):

    (?!):

    (?<=):

    (?<!):

重复

1、{ } 匹配一个字符的重复  **** 注意{3,10} 逗号后不能有空格, 如{3, 10}        

    /^\d{1,3}$/: 最少2个数字,最多4个数字

    /^\d{4,}$/: 最少有4个数字

    /^\d{4}$/: 只能有4个数字

2、* 表示0次或多次重复,等价于{0, }    /^\d*$/

3、?最少0次, 最多1次重复,等价于{0,1}   

4、+ 表示最少出现1次,等价于{1,}

5、\1、\2 重复的子项

    var reg = /(a)(b)(c)\1/;
    var str = "abca";

    // 返回 true: \1是重复第一个子项(a),相当于/(a)(b)(c)(a)/.     \2就是第二项(b)
    console.log(reg.test(str));

修饰符,高级匹配

1、g 匹配的是全局,检索字符串的所有匹配

    如果不加g只匹配第一个后就退出

    let reg = /你妈的|去你妈|傻逼/g;
    let content = '你妈的房子傻逼是用来住的你妈的不是用来炒的去你妈的吧';
    content = content.replace(reg, '***');
    console.log(content)            // ***房子***是用来住的***不是用来炒的***的吧

2、i 匹配忽略大小写

    /java/i.test('JavdaScript');        // true

3、m 进行多行匹配

常用方法

1、match(reg) 将匹配结果返回一个数组

    var arr = '123kasdo34kk234k234234k'.match(/\d+/g);        // 如果不加g,只返回第一个
    console.log(arr);        // ["123", "34", "234", "234234"]

2、test() 如果没有匹配返回false否则返回true

3、search(reg) 查找并返回所在的位置,如果没有匹配的返回-1

    var result = '房地产行业究竟是白银时代还是钻石时代'.search(/钻石/); 
    console.log(result);        // 返回 8

4、content.replace(reg, str) 用于执行检索和替换操作

5、exec() [ɪɡ'zek] 如果找到返回一个数组并存放匹配的结果,如果没有找到返回null

    var result = /白银|钻石/g.exec('房地产行业究竟是白银时代还是钻石时代'); 
    console.log(result);        // ['']

整理经验

1、如果检查全部需要前后加匹配

    /\d+/  只对字符中存在数字就匹配

    /^\d+$/  对字符中全部为数字的进行匹配


2、test()、exec()是对每一个字符串进行匹配,如果为true就不会往下执行,并返回true

    例如: 匹配字符中不能带有.字符
    /[^\.]/.test('123123.');    // 返回true,因为第一个字符就不是.返回true不在往下执行

    /[\.]/.test('23412.34');    // 如果存在就返回true
    或者
    /^[^\.]$/g.test('asdfa.sdf') // 返回true

3、| 或符号只能用到()中,不能在[]中使用

常用示例

1、密码强度

    // 弱密码 - 纯数字、纯字母或纯特殊字符
    /^(?:\d+|[a-zA-Z]+|[!@#$%^&*]+)$/

    // 中密码 - 字母+数字,字母+特殊字符,数字+特殊字符
    /^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&*]+$)[a-zA-Z\d!@#$%^&*]+$/

    // 强密码 - 必须有数字、小写字母、大写字母和特殊字符
    /^(?=.*((?=[!@#$%^&*_]+)[^A-Za-z0-9]))(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[^\u4e00-\u9fa5]{8,16}$/


2、手机号码验证

    /^(139|138|137|136|135|134|178|170|188|187|183|182|159|158|157|152|150|147|139|186|185|170|156|155|130|131|132|189|180|170|153|133)(\d){8}$/.test('13012345678')

    移动号段: /^(139|138|137|136|135|134|178|170|188|187|183|182|159|158|157|152|150|147|139)(\d){8}$/;     

    联通号段: /^(186|185|170|156|155|130|131|132)(\d){8}$/

    电信号段: /^(189|180|170|153|133)(\d){8}$/


3、验证Email - /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/

4、验证中文 - /^[\u4e00-\u9fa5]+$/

5、域名验证 - /^(http(s)?:\/\/)(www)?\.\w+\.(com|cn|net|org)$/

6、手机号前带86或是+86 - /^((\+86)|(86))?(13)\d{9}$/

7、电话号码与手机号码同时验证 - /(^(\d{3,4}-)?\d{7,8})$|(13[0-9]{9})/

8、验证IP地址 - /^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/;    //  匹配0-255, 匹配'255.255.255.255'

9、邮政编码 - /[1-9]{1}(\d+){5}/

10、身份证号码 - /\d{18}|\d{15}/

11、双字节字符串(汉字) - /[^\x00-\xff]*/

12、去除两端空格 - /^\s*|\s*$/

数字正则

    /^\d+$/ - 非负整数(正整数 + 0)

    /^[1-9](\d)+$/ - 正整数(不可以以0开头)  

    /^-(\d)+$/ - 非正整数(负整数 + 0) 

    /^-[1-9]?(\d){0,}$/ - 负整数(-12345), 不可以-012312

    /^[1-9]?(\d)+\.(\d)+$/ - 浮点数   

    /^[+-]?\d+(\.\d{1,2})?$/ - 可以是整数 或 浮点数,并且小数点只能后两位

    ^(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*))$    //正浮点数   
    ^((-\\d+(  //非正浮点数(负浮点数 + 0)   
    ^(-(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*)))$  //负浮点数  

    /^[A-Za-z]+$/ - 由26个英文字母组成的字符串   

    /^[A-Z]+$/ - 由26个英文字母的大写组成的字符串   

    /^[a-z]+$/ - 由26个英文字母的小写组成的字符串  

    /^[A-Za-z0-9]+$/ - 由数字和26个英文字母组成的字符串   

    /^\w+$/ - 由数字、26个英文字母或者下划线组成的字符串

BOM

BOM

BOM   浏览器对象模型    B - Browser    O - Object     M - Model

BOM包含: history、location、navigator、screen 对象

location对象

1、hash: 返回hash值

    https://xxx.com/#sdfsdf       // '#sdfsdf'

2、host: 返回主机地址  'xxx.com'

3、hostname: 返回主机名  'xxx.com'

4、href: 整个url地址  "https://xxx.com/search?q=BOM"

5、origin: 起源  'https://xxx.com'

6、pathName: 路由名

    "https://xxx.com/search?q=BOM"   '/search'

7、port: 端口

8、protocol: 协议  'https'

9、search: 参数 '?q=BOM'

10、reload(): 刷新浏览器

    location.reload(); // 重新加载(有可能从缓存中加载)
    location.reload(true); // 重新加载(从服务器重新加载)

screen

1、width、height: 整天个屏幕的宽、高

2、avaiWidth、avaiHeight: 返回显示屏幕的宽、高 除dock和系统上面的菜单栏

3、pixelDepth: 返回显示屏幕的颜色分辨率

4、updateInteval: 设置或返回屏幕刷新率

history

1、length: 历史记录的个数

2、go(): 指定跳转的历史、-1后退一页,1前进一页

3、back()、forward(): 后退和前进一页
1、appCodeName: 浏览器代码名 'Mozilla'

2、appName: 浏览器名称    'Netscape'

3、appVersion: 浏览器版本  '5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'

4、browserLanguage: 浏览器语言

5、cookieEnabled: 是否启用了cookie 返回Boolean

    如果浏览器关闭cookie,当获取cookie时, document.cookie 返回的是空字符串

6、cpuClass: 返回浏览器系统的cpu等级

8、onLine: 是否处于脱机模式,Boolean

9、platform: 浏览器的操作平台

10、systemLanguage: 系统语言

11、userAgent: 客户机发送服务器的 user-agent 头部的值

12、userLanguage: 返回 OS 的自然语言设置


** 检测插件  ie无效
function hasPlugin(name){
    name = name.toLowerCase();
    for (var i = 0; i < navigator.plugins.length; i ++){
        if (navigator.plugins[i].name.toLowerCase().indexOf(name) > -1){
            return true;
        }
    }
    return false;
}

** 检测Flash
function hasPlugin(name){
    name = name.toLowerCase();
    for (var i = 0; i < navigator.plugins.length; i ++){
        if (navigator.plugins[i].name.toLowerCase().indexOf(name) > -1){
            return true;
        }
    }
    return false;
}

function hasIEPlugin(name){
    try{
        new ActiveXObject(name);
        return true;
    }catch(ex){
        return false;
    }
}

function hasFlash(){
    var result = hasPlugin("Flash");
    if (!result){
        result = hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
    }
    return result;
}

console.log(hasFlash()) //true

window 对象

1、window.open(url, target, param): 打开一个新窗口

2、window.close(): 关闭一个窗口

3、setInterval()、clearInterval()

4、setTimeout()、clearTimeout()

5、screenLeft、screenTop: 浏览器当前窗口居屏幕的左、上角的位置  

    兼容:
    screenLeft || screenX
    screenTop || screenY

6、innerWidth、innerHeight: 浏览器可视区的宽高、包括滚动条

    let winHeight = window.innerHeight;

7、moveTo(x, y): 移动到屏幕左上角的位置

8、moveBy(0, 100): 向下移动100像素

9、resizeTo(x,y)、resizeBy(w, h)

offset 页面元素偏移量

1、offsetWidth、offsetHeight: 获取当前元素宽高,相当于 width + padding + border

2、offsetLeft、offsetTop: 获取元素到父级元素定位的左、上偏移,如果父级不是定位就以body元素为定位

3、offsetParent: 获取最近一个带有定位的父级元素

4、clientWidth、clientHeight: 元素本身的宽高、不包括padding和border

    兼容
    document.documentElement.clientWidth || document.body。clientWidth
    document.documentElement.clientHeight || document.body。clientHeight

scroll 滚动类

窗口滚动条或带滚动条元素

1、scrollWidth、scrollheight: 对象内部实际内容的宽、高

2、scrollTop、scrollLeft: 被卷部分的顶部和左侧部分

    只挂载到了Element元素中,window和document下都没有

    let topValue = document.documentElement.scrollTop || document.body.scrollTop;       // 获取整个页面巻上去的高度和兼容方法

    let topValue = document.querySelector('#sider').scrollTop;      // 针对某个元素


3、onscroll: 侦听滚动条事件

client 鼠标所在的可视区坐标

1、clientX、clientY: 获取鼠标可视区的位置  clientX = width + padding

2、clientLeft、clientTop: 获取鼠标在可视区域的位置

3、pageX、pageY: 获取鼠标在页面中的位置, pageX = clientX + 页面滚动出的距离

node.onclick = function(evt){
    let evt = evt || window.evnet;
    console.log(evt.pageX, evt.pageY);
    console.log(evt.pageX, evt.pageY);
}

事件

1、target: 点击的目标阶段事件,ie8之前使用srcElement

    var oT = evt.target || srcElement; console.log(oT);     // <p>xxxx</p>

2、currentTarget: 事件流的捕获,目标及冒泡阶段

3、addEventListener()、attachEvent(): 注册事件

    addEventListener('click', fn, false);

ES5

script标签

1、async: 异步下载当前脚本,不阻塞后续代码的执行

2、charset: 字符集

3、defer: 表示当前脚本延迟到文档完全被解析和显示后在执行 defer="defer"

4、src: 文件路径

5、language: 语言

6、type: 脚本类型

'use strict' 严格模式

作用域和作用域链

作用域: 变量的有效范围,函数从内往外搜索变量,如果内部没有变量就去外部搜索直接全局对象

作用域链: 决定哪些变量能够被当前函数访问及访问顺序

    函数对象有一个[[Scope]]属性,包含了函数被创建作用域中对象的集合,集合被称为函数的作用域链scope chain,它决定了哪些数据能被函数访问

    function doSomething(){
            var blogName="Jessica";
            function innerSay(){
                    alert(blogName);
            }
            innerSay();
    }
    alert(blogName);        //脚本错误
    innerSay();             //脚本错误

变量生命周期:全局的变量是永久的,函数内的局部变量当退出函数时,局部变量即消毁,

预解析

JS执行时先将代码中所有 var定义变量和function(){} 进行提取,函数内部变量除外。

将var的变量赋为undefined

将函数都为函数本身function getName(){},所以在调用函数时无论在前还是在后都会被调用。

Example:
    var add = 'bbb'; 
    function add(){console.log('aaa')} 
    add();      报错

闭包

闭包: 函数嵌套,内部函数调用外部函数的局部变量,内部函数执行完后自动消毁,外部函数的变量不会被回收一直保存在内存中.

<script>
    var fun = function(){
        var a = 1;
        return function(){
            a++;
            alert(a);
        }
    }

    var f = fun();        // 这里返回了匿名函数的引用,里面的局部变量就不会被消毁
    f();    // 2
    f();    // 3
    f();    // 4
</script>

数据类型

JS的七种数据类型: Number、String、Boolean、Undefined、Object、Function、Symbol

一、 获取数据类型

    获取数据的类型: 返回的值(number、string、boolean、array、object、function、undefined、symbol)

    Object.prototype.toString.call(val) - 获取JS私有的 Class 属性, 这个隐藏的属性是不能被改的

    // 判断类型
    function returnType(val) {
        let typeName;
        if (typeof val === 'object') {
            let typeName = Object.prototype.toString.call(val);

            if (typeName == '[object Array]') {
                return 'array'
            } 
            else if (typeName == '[object Object]') {
                return 'object'
            }
            else if(typeName == '[object Null]'){
                return 'null'
            }
        } 
        else {
            return typeof val;
        }
    }


二、NaN 非数值

    isNaN() 是否是一个NaN非数值, 如果是数字返回false, 否则返回true

        isNaN(NaN);     // true
        isNaN(10);      // false
        isNaN('10');    // false 转换后是一个数字
        isNaN('blue');  // true 转换后不会是一个数字
        isNaN(true);    // false true转换后为1是一个数字      


三、类型转换

    String to Number: 类型转换只支持十进制(30)、二进制(0b111)、八进制(0o13)、十六进制(0xFF)

    Number比parseInt和parseFloat更好的选择,一些古老的浏览器parseInt还支持0开头数字的八进制前缀,这是错误的,在任何环境下都建议传入parseInt第二个参数

    1、Number() 布尔转换成1或0,null返回0,undefined返回NaN

    2、parseiInt(num, 10): 第二个参数来规则用哪个进制来转换

    3、parseFloat(): 直接将字符串以十进制来转换

包装类

var str = '1234567';
str.length;        // 返回7

str原始值只是一个字符串,为什么会有属性和方法,它经历了一个过程叫『包装类』
JS在执行些方法的时候会隐式的转成 new String(str),执行完后在乐逍毁掉

函数

一、函数没有重载: 当两个函数名相同,后面的函数会覆盖掉之前的函数

    function getUserName(){
        console.log('a');
    }

    function getUserName(){
        console.log('b');
    }

    getUserName();      // 'b'


二、声明函数和匿名函数

    function person() {  ...  };          // 声明
    var person = function() {  ...  }     // 匿名

    Example:

        getName();          // b
        var getName = function(){       // 优先级要高于声明函数,但要必须执行到这里才有效
            console.log('a');
        };

        getName();          // a

        function getName(){
            console.log('b');
        }
        getName();          // a


三、函数参数

    1、形参、实参

        function add(a, b){ return a+b }    // 形参

        add(1,2)    // 实参


    2、arguments数组: 函数参数的数组

    3、callee 函数的调用当前函数的本身,可以使用arguments.caller(), 可以用于递归

        function factorial(num){
            if(num < 1){
                return 1;
            }
            else{
                return num * arguments.callee(num-1);
            }
        }

    4、caller 返回被调用函数的本身

        function outer() {
            inner();
        }

        function inner() {
            alert(arguments.callee);        // function inner(){ ... }
            alert(arguments.callee.caller); // function outer(){ ... }
        }

        outer();

四、如果函数没有return返回undefined

    var fn = function(){ }; 
    fn();       // undefined

call()、apply()、bind()

Function.prototype.call() 和 Function.prototype.apply() 用于改变函数的this指向

一、call无参

    var obj1 = {
        name: 'siguang',
        getName: function(){
            return this.name;
        }
    }
    var obj2 = {
        name: 'lulu'
    }
    console.log(obj1.getName());  // siguang

    // 注意这里是将getName中的this指定指向了obj2,并且执行了getName()函数
    var n1 = obj1.getName.call(obj2);
    console.log(n1);        // lulu


二、apply有参

    var objA = {
        num: 10,
        add: function(a, b){
            return a + b + this.num;
        }
    }
    var objB = {
        num: 20
    } 

    var n1 = objA.add(1, 2);
    console.log(n1);    // 13

    var n2 = objA.add.call(objB, 1, 2);     // 如果objA.add.apply(objB, [1,2]);
    console.log(n2)     // 23


三、bind(): 一个函数绑定之后,可以保持传递this的上下文

    bind与call、apply的用法不同,但作用是一样的.

    var obj = {
        nameStr: 20,
        getName: function(){
            setTimeout(function(){
                console.log(this.nameStr);
            }.bind(obj), 10)
        }
    }

    // 输出20,如果不加bind(),this指向window所以输出的是undeined
    obj.getName();

void(0)

这个操作符允许插入一个计算结果等效于undefined的表达式。

void操作符经常仅仅是用来获得undefined值,比如经常使用到的“void(0)”(这等效于“void 0”)

当浏览器遇到一个javascript:URI,它会运算带有URI的代码,然后将计算结果替换当前页面的内容,除非它的返回值是undefined。void操作符可以被用于返回undefined

<a href="javascript:void(0);">Click here to do nothing</a>

装箱、拆箱转换

一、装箱: 把基本类型转换为对应的对象

    var symbolObject = Object(Symbol("a"));
    console.log(typeof symbolObject);                   // object
    console.log(symbolObject instanceof Symbol);        // true 是Symbol的实例
    console.log(symbolObject.constructor == Symbol);    // true


二、拆箱

    对象到String和Number转换同都遵循『先拆箱在转换』的规则,通过拆箱把对象变成基本类型,在从基本类型转为string或number

    toString(): 将该对象的原型始以字符串形式返回   xx.toString();       // 'xx'

    valueOf(): 返回最适合该对象的类型的原始值

表达式

var testA = 3 && 2;             // 返回 2,如果左侧为真返回右侧,否则返回左侧

var testB = 0 || 3;             // 返回3,如果左侧为假返回右侧

var a = 1; console.log(!!a);    // 返回true,!!强制转换成布尔值

var a = '123.563'; console.log( +a );  // 123.563,+转换成数值类型

语句

for(var i=0; i<10; i++){}

do{....} while(express)

while(){ ... }

for( in ){}

break 退出整个循环        continue 跳出当前循环,继续执行下一个循环

switch case default

定时器的运行机制

JavaScript是通过事件循环(event loop)来实现的,事件循环机制也就是今天要说的JavaScript运行机制。

第一,判断JS是同步还是异步,同步进入主线程,异步则进入event table。

第二,异步任务在event table中注册函数,当满足触发条件后,被推入event queue(事件队列)。

第三,同步任务进入主线程后一直执行,直到主线程空闲,才会去event queue中查看是否有可执行的异步任务,如果有就推入主线程

异步为了避免一些长时间任务造成的无意义等待,和假死状态 - ajax、定时器、Promise

Example:

    // HTML5规范规定最小时间不能小于4ms(毫秒),如果小于4会被当4来处理,Chrome可以设置1ms
    console.log(1);
    setTimeout(function(){
        console.log(2);
    }, 0);
    console.log(3);         // 1、3、2

JS异步有哪些方式

1、setTimeOut()

2、Promise

3、Generator

4、async、await

5、ajax

宏任务和微任务

JS的运行机制。也就是事件循环。解释一下:

    第一,执行一个宏任务(主线程的同步script代码),过程中如果遇到微任务,就将其放到微任务的事件队列里。

    第二,当前宏任务执行完成后,会查微任务的事件队列,将全部的微任务依次执行完,再去依次执行宏任务事件队列。

    宏任务:包括整体script代码,setTimeout,setInterval

    微任务:Promise,process.nextTick。

setTimeout(() => {
    console.log(1) 
}, 3000); 

new Promise((resolve, reject) => { 
    console.log(2); 
    resolve('2') 
})
.then(function(){  
    console.log(3) 
});

console.log(4);                // output 2、4、3、1

事件

一、事件机制: 事件捕获 和 事件冒泡, IE11之前没有捕获

二、事件委托

    事件委托(也称事件代理): 将事件绑定到父元素上,利用冒泡机制来对点击的元素进行处理

    <div id="boxList">
        <ul>
            <li data-attr="a1">aaa</li>
            <li data-attr="a2">bbb</li>
            <li data-attr="a3">ccc</li>
        </ul>
    </div>

    <script type="text/javascript">
        var oList = document.querySelector('#boxList');
        oList.onclick = function(e){
            var arrtName = e.target.getAttribute('data-attr');
            console.log(arrtName);
        }
    </script>


三、自定义事件

四、onLoad与DOMContentLoaded事件的区别

    onLoad: 是当所有资源都加载完成后在执行onLoad函数内的程序

    DOMContentLoaded: 是当DOM树加载完成后就执行此函数内的程序


五、onmouseover、onmouseout与onmouseEnter、onmouseLeave

    onmouseover、onmouseout 会冒泡

    onmouseEnter、onmouseLeave 不会冒泡


六、addEventListener(事件类型, 执行函数, boolear): 第三个参数,如果是true表示在捕获取中调用事件,false冒泡时调用

    这里执行的函数不会被重载

    var oSendBtn = document.querySelector('#sendBtn');      // 点击会输出'aa', 'bb'

    oSendBtn.addEventListener('click', function(){
            console.log('aa');
    }, false);

    oSendBtn.addEventListener('click', function(){
            console.log('bb');
    }, false);

概念

一、加载非阻塞脚本:  

    浏览器遇到 <script> 标签时,页面加载都会停下来,先执行js代码,然后在继续加载(因为不知道脚本里有没有document.wirte()
    来向页面写内容,所以会需要先执行完js文件在继续)

    使用动态创建DOM元素,将脚本加载放到</body>之前来加载,这样不会影响页面的内容展示


二、按需加载: 可以分图片按需加载,js文件按需加载、数据接需加载

    图片按需加载使用的lazyload

    JS按需加载类似模块化开发,只对依赖的文件进行加载


三、图片预加载: 通过new Images()来创建图像对象提前将图片进行加载

    function preloadImg(url) {
        var img = new Image();
        img.src = url;
        if(img.complete) {
            //接下来可以使用图片了
            //do something here
        }
        else {
            img.onload = function() {
                //接下来可以使用图片了
                //do something here
            };
        }
    }

跨域的解决方法

由于同源策略,安全性,ajax不同域下的数据不可以调用

跨域的产生: 1、同域名不同端口        2、同域名不同协议        3、主域和子域之间        4、子域和子域之间

解决跨域的方法: 

一、JSONP

    JSONP利用script标签中的src属性,src属性没有跨域限制,通过url的参数将回调函数的名称和数据请求给服务器,服务器接收到url参数进行处理,并将数据挂载到回调函数的参数并执行回调函数,客户端有与回调函数名相同,来处理这些数据

    // 处理回调函数数据的函数
    function doSomething(data) {
            // 对data处理
    }
    var script = document.createElement("script");
    script.src = "http://www.b.com/b.html?callback=doSomething";
    document.body.appendChild(script);


二、document.domain: 

    适用于主域相同子域不同,比如 www.renrendai.com 和 action.renrendai.com

    例如: 两个域下各有a.html和b.html, a通过iframe嵌到另一个子域b.html是无权访问b.html文档内的元素, 所以通过document.domain来设置

    a.html: 
        document.domain = "www.we.com";
        var iframe = document.createElement("iframe");
        iframe.src = "http://a.we.com/b.html";
        document.body.appendChild(iframe);
        iframe.onload = function() {
            console.log(iframe.contentWindow....); // 在这里操作b.html里的元素数据
        }

    b.html:
        document.domain = "www.we.com";       // b页面必须要设置a.html


三、HTML5 postMessage() 处理iframe跨域问题

    如果在一个主域中的a.html嵌套个 <iframe src="http://www.b.com/b.html" frameborder="0"></iframe>

    postMessage有两个接口: postMessage(send) 发送数据和 onmessage接收数据事件通过e.data来获取到

    Example: 
        // a.html
        <iframe src="http://www.b.com/b.html" frameborder="0" id="messageId"></iframe>

        var oMessage = document.getElementById('messageId');
        window.onload = function(){
            window.addEventListener('message', function(e){
                console.log(e.data);    // 接收b的数据
            }, false);
            oMessage.postMessage('发送给b的数据', 'http://www.b.com/b.html');
        }

        // b.html
        window.onload = function(){
            window.addEventListener('message', function(e){
                console.log(e.data);    // 接收a的数据
            })
            window.parent.postMessage('发送给a的数据', 'http://www.a.html/a.html');
        }

    传统的iframe跨域使用方法: http://www.cnblogs.com/snandy/p/3900016.html


四、window.name + iframe

    window.name原理是利用同一个窗口在不同页面共用一个window.name,这个需要在a.com下建立一个代理文件c.html,使同源后a.html能获取c.html的window.name.

        // a.html
        var iframe = document.createElement("iframe");
        iframe.src = "http://www.b.com/b.html";
        document.body.appendChild(iframe); // 现在a.html里建一个引用b.html的iframe,获得b的数据

        var flag = true;
        iframe.onload = function() {
            if (flag) {
                iframe.src = "c.html";          // 这里在去加载c.html
                // 判断是第一次载入的话,设置代理c.html使和a.html在同目录同源,这样才能在下面的else取到data
                flag = false;
            } 
            else { 
                // 第二次载入由于a和c同源,a可以直接获取c的window.name
                alert(iframe.contentWindow.name);

                iframe.contentWindow.close();
                document.body.removeChild(iframe);
                iframe.src = '';
                iframe = null;
            }
        }

        // b.html
        window.name = "这是 b 页面的数据";


五、window.location.hash + iframe

    b.html将数据以hash值的方式附加到c.html的url上,在c.html页面通过loaction.hash获取数据后传到a.html

    // a.html
    var iframe = document.createElement("iframe");
    iframe.src = "http://www.b.com/b.html";
    document.body.appendChild(iframe); // 在a页面引用b
    function check() { 
        // 设置个定时器不断监控hash的变化,hash一变说明数据传过来了
        var hashs = window.location.hash;
        if (hashs) {
            clearInterval(time);
            alert(hashs.substring(1));
        }
    }
    var time = setInterval(check, 30);

    //b.html
    window.onload = function() {
        var data = "this is b's data"; 
        var iframe = document.createElement("iframe");
        iframe.src = "http://www.a.com/c.html#" + data;         
        document.body.appendChild(iframe); // 将数据附加在c.html的hash上
    }

    //c.html
    // 获取自身的hash再传到a.html的hash里,数据传输完毕
    parent.parent.location.hash = self.location.hash.substring(1);


六、CORS跨域资源共享

    1、CORS概念: 是指跨域资源共享, 用于解决前端跨域问题, 使用自定义头部让浏览器与服务器进行沟通, 来进行请求成功或失败

        原理: 服务器对header设置一个Access-Control-Allow-Origin: *, 开启跨域请求。

        *表示接受所有域名的请求。也可以指定特定的域名 Access-Control-Allow-Origin: http://www.client.com。


    2、CORS优点: 跨域最常用的是JSONP但这种方式是通过Get的方式请求src完成的,很多跨域问题JSONP无法解决,比如: 

        1)post请求跨域

        2)"script error" 的脚本错误提示

        3)canvas中无法获取跨域图片的信息,如果使用CORS上面几个问题就可以解决


    3、CORS缺点: 

        1)cookie不会随请求发送,也不会响应

        2)不能设置请求头的Content-Type字段

        3)不能访问响应头信息

面向对象

面向对象的特点: 封装、继承、多态

对象组件: 私有、公有属性、方法和特权方法

一、对象的数据属性和访问器属性(getter、setter)

    var o = { a: 1 };
o.b = 2;
console.log(o.a, o.b); //1 2

二、constructor属性: 指向这个原型的构造函数,如果是类式继承需要修改子类的constructor的指向,如果不改子类会指向父类.

三、原型和原型链: 

    prototype原型: 在创建函数的时候JS会为这个函数自动加上prototype属性

    原型链: 每一个构造函数都有一个prototype, prototype包含一个指向构造函数的指针, 而实例包含指向原型的对象的指针, 都是通过 __proto__ 属性来指向

    1、构造函数实例化后,prototype下的所有属性和方法都为公用的一套, 这样为了节省资源提高性能

    2、优先级: 如果同时在构造函数内或prototype中定义相同的属性或方法名, 会先找到执行构造函数内的属性或方法, 如果没有在到prototype中查找。

            __proto__属性: __proto__是实例与prototype之间的链接,实例的__proto__指向构造函数的prototype.function F(){}; 

            var f = new F(); 
            console.log(f.__proto__ === F.prototype);           // true
            Object.prototype是顶级对象,所有对象都继承它

四、继承

    每个对象都是由Object.prototype对象继承的

        继承分为: 类式继承、原型链继承、拷贝继承。

        1、类式继承: 

            function Parent(){}
            Parent.prototype.say = function(){ 
                console.log('haha')
            }

            function Childer(){}

            /* 将第一个类的实例赋给第二个类的原形,类式继承的原因
            *  类的原型对象作用就是为类的原型添加公有方法,但不能直接访问这些属性和方法,必须通过原型prototype来访问
            */
            Childer.prototype = new Parent();   

            // 上一步执行后prototype的constructor会指向Parent,所以需要修正回来
            Childer.prototype.constructor = Childer;    
            Childer.prototype.getAuthor = function(){ console.log('siguang') }


        2、原型链继承: 

            // 原型链式继承
            /*
            * 流程:
            * 1、clonePlan调用blood属性会在clonePlan查找所有属性,
            * 2、如果没有找到在看clonePlan的__proto__指象哪里,这里指向了F,到F对象下的prototype下查找
            * 3、plane将prototype赋给了F的prototype所以最终找到了blood属性
            */

            function extend(obj){
                    var F = function(){};
                    F.prototype = obj;
                    return new F();
            }

            // 定义一个类
            var Plane = function(){
                    this.blood = 100;
                    this.attackLevel = 1;
                    this.defenseLevel = 1;
            }
            Plane.prototype = {
                    getBlood: function(){
                            console.log(this.blood);
                    },
                    getAttackLevel: function(){
                            console.log(this.attackLevel)
                    }
            }
            var plane = new Plane();

            // 将类通过extend函数继承过来
            var clonePlan = extend(plane);
            clonePlan.blood = 1234;
            clonePlan.attackLevel = 4567;

            clonePlan.getBlood();               // 1234
            clonePlan.getAttackLevel();         // 4567


        3、拷贝继承

            function extend(parent, childer){
                for(var key in parent){
                    childer[key] = parent[key];
                }
            }

            extend(a.prototype, b.prototype);


        4、Object.create()继承

            function Car(desc){
                this.desc = desc;
                this.color = 'red'
            }

            Car.prototype = {
                getInfo: function(){
                    return `color: ${this.color}, desc: ${this.desc}`
                }
            }

            // 注意这里的name : {value: 'lulu'} 必须是对象,必须是value在根一个值,要不报错
            var child = Object.create(Car.prototype);
            child.desc = 'aaa';
            child.color = 'bbb';

            // 改变子类不会影响到父类
            console.log(child);
            var childCar = child.getInfo();
            console.log(childCar)       // color: bbb, desc: aaa

            var oCar = new Car('ccc');
            console.log(oCar.getInfo());    /// color: red, desc: ccc


五、SuperClass.prototype = {} 与 SuperClass.prototype.getName = function(){} 区别

    一个是将对象覆盖prototype, 一个是将方法添加到prototype中

    存在的问题,SuperClass.prototype = {}这种方式,实例的对象没有constructor,

Ajax

一、XMLHttpRequrest 缓存

    缓存只有在get请求中存在,如果服务端设置了缓存,如果在缓存失效前请求就会取到缓存的数据,解决有两种方法:

    1、加If-Modified-Since头

        xhr.setRequestHeader('If-Modified-Since', '0');

        jquery中设置  $.ajax({ cache: false })

    2、给请求的URL后加参数 

        let sendUrl = "http://host/getUser"+"?"+Math.random();


// 创建一个XMLHttpRequest对象
var xhr = window.XMLHttpRequrest ? new XMLHttpRequrest() : new ActiveXObject("Microsoft.XMLHTTP");   

属性: 服务器响应

    1、reponseText: 字符串响应数据

    2、responseXML: 获取XML响应数据

    3、timout: 设置超时请求时间

    4、responseType: 设置返回数据类型

            1、text: 字符串      2、document: Document对象       3、json: json数据       4、blob: 二进制对象       5、arrayBuffer: 二进制

方法: 

    1、open(请求类型,请求地址,同步/异步): 请求类型

    2、send(): 请求发送到服务器

    3、setRequestHeader(key,value): 设置请求头

    4、getResponseHeader(header)、getAllResponseHeaders(): 获取响应头

事件: 

    1、onabort: 停止传输

    2、onerror: 错误

    3、onload: 

    4、ontimout: 超时执行的事件

    5、onreadystatechange: 请求发送到服务器时,接收一些响应

        readyState: XMLHttpRequest的状态,

            0: 请求未初始化    1、服务器连接已建立      2、请求已接收     3、请求处理中     4、请求已完成,已响应

        status:  200: 成功  404:  未找到资源

        xhr.onreadystatechange = function(e){
            if(this.readyState == 4 && this.state == 200){
                console.log(this.reponseText)
            }
        }

    6、upload: 上传 XMLHttpRequestUpload

        function uploadFile() {  
            // 创建FormData对象
            var fd = new FormData();
            // 添加值
            fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]); 

            // 创建XMLHttpRequest()请求
            var xhr = new XMLHttpRequest();  
            // 文件上传时侦听progress事件
            xhr.upload.addEventListener("progress", uploadProgress, false);  

            xhr.addEventListener("load", uploadComplete, false);    // 载入 
            xhr.addEventListener("error", uploadFailed, false);     // 错误
            xhr.addEventListener("abort", uploadCanceled, false);   // 终止

            // 请求方式和地址
            xhr.open("POST", "test2.php");  
            // 发送请求到服务器
            xhr.send(fd);  
        }

        function uploadProgress(evt) { 
            // evt.loaded 当前上传的大小, evt.total 文件总大小
            if (evt.lengthComputable) {  
                var percentComplete = Math.round(evt.loaded * 100 / evt.total);  
                document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';  
            }  
            else {  
                document.getElementById('progressNumber').innerHTML = 'unable to compute';  
            }
        }

        function uploadComplete(evt) {  
            /* This event is raised when the server send back a response */  
            alert(evt.target.responseText);  
        }

        function uploadFailed(evt) {  
            alert("There was an error attempting to upload the file.");  
        }

        function uploadCanceled(evt) {  
            alert("The upload has been canceled by the user or the browser dropped the connection.");  
        }

content-type四种类型

get请求包括请求头、状态行

post请求包括请求头、状态行、请求主体(主体类型设置就是content-type来处理)

Content-Type:

一、application/x-www-form-urlencoded: 浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据

    jquery和ajax的默认的方式 content-type:「application/x-www-form-urlencoded;charset=utf-8」

    header:
    POST http://wwwexamplecom HTTP/11 
    Content-Type: application/x-www-form-urlencoded;charset=utf-8 

    ** Form Data

        incomeTime: "16:25:13"
        serialNumber: "223"
        incomeBank: "中央银行"
        incomeAccount: "穷逼"


二、multipart/form-data: 一般用来上传文件,必须让 form 的 enctyped 等于这个值

    content-type: multipart/form-data

    POST http://wwwexamplecom HTTP/11 
    Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA 

    ** Request Payload

            ------WebKitFormBoundaryrGKCBY7qhFd3TrwA 
            Content-Disposition: form-data; name="text" 

            title 
            ------WebKitFormBoundaryrGKCBY7qhFd3TrwA 
            Content-Disposition: form-data; name="file"; filename="chromepng" 
            Content-Type: image/png 

            PNG  content of chromepng  
            ------WebKitFormBoundaryrGKCBY7qhFd3TrwA-- 


三、application/json: 告诉服务端消息主体是序列化后的 JSON 字符串

    POST http://wwwexamplecom HTTP/11 
    Content-Type: application/json;charset=utf-8 

    // ajax请求
    var data = {'title':'test', 'sub' : [1,2,3]};
    $ajaxpost(url, data)success(function(result){

    });

    // 发送
    POST http://wwwexamplecom HTTP/11
    Content-Type: application/json;charset=utf-8

    ** Request Payload

        {"title":"test","sub":[1,2,3]}


四、text/xml: XML文件作为编码方式的需要用到的类型

    POST http://wwwexamplecom HTTP/11
    Content-Type: text/xml

    ** Request Payload


五、HTML5中的fromData异步上传表单

    这里注意需设置 content-type:false 和 processData: false

    function upThumbSubmit() {
        if(!windowFormData) { 
            alert('your brower is too old');
            return false;
        }
        var formData = new FormData($( "#upForm" )[0]);
        var upLoadFile = documentquerySelector('upfile')files[0];
        formDataappend('file': upLoadFile);

        $ajax({
            url:'?c=api&a=upload',
            type:'post',
            data:formData,
            processData: false,        // 不会被序列化
            contentType: false,        
            dataType:'json',
            success:function(data){
                alert(data);
                return false;
            }
        });
    }

iframe父子页面的通信

Example:

    parent.html:
        <body>
            <iframe src="child.html" frameborder="0" id="child"></iframe>
        </body>

    childe.html:
        <body>
            <div id="box"></div>
        </body>

一、父页面获取子页面

    <script>
        var myIframe = document.querySelector('#child'), 
                childDocument;

        if(myIframe.document){
            childDocument = myIframe.docuemnt;
        }
        else{
            childDocument = myIframe.contentWindow.docuemnt;
        }

        childDocument.querySelector('#box').innerHTML = 'xxxx';
    </script>

    1、先获取iframe节点

        var myIframe = document.querySelector('#child');        // 或 myIframe = window.frames['child'];

    2、获取iframe页面的document对象

        // ie浏览器
        var childDocument = myIframe.docuemnt;

        // 其它浏览器
        var childWindow = myIframe.contentWindow;     // 获取iframe的window对象
        var childDocument = myIframe.contentWindow.docuemnt;    // 获取iframe的document对象
        var childDocuemnt = myIframe.contentDocument;   // 也是获取document对象  与 myIframe.contentWindow.docuemnt 相同

    3、向id='box'设置内容

        childDocument.querySelector('#box').innerHTML = 'xxxx';


二、子页面获取父页面

    1、获取父页面的document对象

        var parentDocument = window.parent.document;

    2、如果iframe嵌套多个iframe,想直接取到最顶层的iframe

        var selfDocument = window.self.document;

——————— ES5 API ————————

提供全局的JSON对象

1、JSON.parse(): 将字符串转成对象

2、JSON.stringify(): 将对象转成字符串

Array扩展

1、push(): 向数组最后插入内容   unshift():向数据最前面插入一项

2、pop(): 删除数组最后一项内容  shift(): 删除数组第一项内容

    var arr = [1, 2, 3];   
    console.log(arr.pop());     // 3
    console.log(arr)    // [1, 2]

3、reverse(): 数组顺序颠倒

4、sort(): 排序

    let arr = [1, 123, 23, 4, 125, 6, 2, 31];
    arr.sort(function(v1, v2) {
        return v1 < v2 // 从大到小排列
    })

5、concat(): 两个数组进行合并, 也可以拷贝成为一个新数组,而不是带指向

    var arrA = [1,2,3];
    var arrB = arrA.concat();
    arrB.push(5,6,7);
    console.log(arrA);  // [1,2,3]
    console.log(arrB);  // [1,2,3,5,6,7]

6、slice(开始,结束): 返回一个子数组,  如果结束参数不传为从开始取到最后的值

    let arr = [125, 123, 31, 23, 6, 4, 2, 1];
    let newArr = arr.slice(2, 5);  
    console.log(newArr, arr);        // [31, 23, 6]    [125, 123, 31, 23, 6, 4, 2, 1]

7、splice(): 用于替换、插入、删除

    splice(1,3): 删除 下标1-3的数据
    splice(3,0, 'insert'): 插入 在位置3一个'insert'字符串
    splice(2,4, 'replce'): 替换 将2-4的数组用 'replce'符

8、indexOf(): 查找数组中指定的字位的位置,未找到返回-1

    var arr = [1,2,3,4,5,6];  arr.indexOf(3);         // 返回2

9、lastIndexOf(): 查找数组中指定的字位的位置,从后向前查找,未找到返回-1


* 迭代方法

10、every(): 每一项为true,结果返回true

    // 数组中是否包含大于2的数
    var num = [1,2,3,2,1];
    var result = num.every(function(item,index,array) {    // item: 1, index: 0, array: [1,2,3,2,1]
        return (item > 2);
    })
    console.log(result);        // true


11、some(): 有一项为true就不会往下执行,并返回true

    var dwarfPlanets = ["ceres", "pluto", "haumea", "makemake", "eris"];
    var result = dwarfPlanets.some(function(element) {
        return (element === "pluto");
    });   
    console.log(result)     // true


5、filter(): 条件中返回true结果,重新返回一个新数组

    var arr = [1, 2, 3, 2, 5, 7];
    var result = arr.filter(function(item,index,array){
        return (item > 2);
    })
    console.log(result);        // [3, 5, 7];


6、forEach(): 遍历数组, forEach无法跳出循环, 只能通过try...catch

    var arr = ['lulu', 'siguang', 'mama', 'baba'];
    arr.forEach(function(item, index, arr){  // lulu  0  ["lulu", "siguang", "mama", "baba"]
        console.log('name:'+item, index, arr);
    })


7、map(): 将每次return的数据,最终组成一个数组返回

    var srcColors = [
        {r: 255, g: 255, b: 255 },
        {r: 128, g: 128, b: 128 },
        {r: 0,   g: 0,   b: 0   }
    ];

    var newColor = srcColors.map(function(item, index, arr){         
        return item.r;
    })
    console.log(newColor);        // 返回 [255, 128, 0]


8、reduce(上次执行的结果,当前值,当前索引,数组对象)、reduceRight(): 归并数组,每次循环都会返回上一次值和当前值

    var val = [1,2,3,4,5];
    var sum = val.reduce(function(prev, cur, index, arr){   // prev 第一次执行的是1, 第二次执行的就是上次1+2返回的结果
        return prev + cur;   
    })
    console.log(sum);   // 15

对象属性和方法

1、__proto__: 对象实例与prototype之间的连接,原型链

2、prototype: 原型,公用的,节省内存开支,查找先去对象本身找属性和方法,如果没有到prototype下查找

3、constructor: 保存用于创建当前对象的构造函数名

4、toString()、valueOf()

5、delete: 删除对象属性

6、hasOwnProperty(propertyName): 判断对象属性是否在对象中(而不是prototype原型中) var obj = {name: 'aaa'}; obj.hasOwnProperty('name')

    function Persion(){
        this.name = 'siguang';
    }
    Persion.protoType = {
        age: 35,
        getName: function(){
            return this.name;
        }
    }
    let oPer = new Persion();
    oPer.hasOwnProperty('name');        // true
    oPer.hasOwnProperty('age');            // false

7、isPrototypeOf(object): 判断传入的对象是否是传入对象的原型

    var o = new Object();
    Object.prototype.isPrototypeOf(o)

8、instanceof: 用来判断一个构造函数的prototype属性是否在另一个检测对象的原型链上

    class A {};
    let oA = new A():
    console.log(oA instancof A);        // true

9、in: 属性是否在对象中能访问,返回true或false

    function Persion(){
        var sex = '男';
        this.name = 'siguang';
    }
    Persion.prototype.age = 'haha';

    var p1 = new Persion();
    console.log('name' in p1);      // true
    console.log('age' in p1);       // true
    console.log('sex' in p1);       // false;


10、Object.create(o, p): 可以创建一个干净的对象,给o对象创建一个prototype,如果p对象存在

    var oA = Object.create(null);    // 创建一个干净的对象,没有__proto__属性
    var oB = {};        // 存储__proto__

    function Car(desc){
        this.desc = desc;
        this.color = 'red'
    }

    Car.prototype = {
        getInfo: function(){
            return `color: ${this.color}, desc: ${this.desc}`
        }
    }

    // 注意这里的name : {value: 'lulu'} 必须是对象,必须是value在根一个值,要不报错
    var child = Object.create(Car.prototype);
    child.desc = 'aaa';
    child.color = 'bbb';

    // 改变子类不会影响到父类
    console.log(child);
    var childCar = child.getInfo();
    console.log(childCar)       // color: bbb, desc: aaa

    var oCar = new Car('ccc');
    console.log(oCar.getInfo());    /// color: red, desc: ccc

    1) Object.create()与new Object()的区别

        var Base = function () {}
        var o1 = new Base();
        var o2 = Object.create(Base);

        Object.create(null) 是创建一个空对象,这个对象不继承Object.prototype原型链上的属性或方法


11、Object.defineProperty(obj, prop, descriptor): 对象新增或修改一个属性会执行set()、get()方法来通知

    参数: obj 目标对象     prop需要定义的属性      descriptor该属性拥有的特性,可设置的值有

    descriptor的值: 

        value 属性的值,默认为 undefined。

        writable 该属性是否可写,如果设置成 false,则任何对该属性改写的操作都无效(但不会报错),默认为 false。

        get 一旦目标对象访问该属性,就会调用这个方法,并返回结果。默认为 undefined。

        set 一旦目标对象设置该属性,就会调用这个方法。默认为 undeinfed。

        configurable 如果为false,则任何尝试删除目标属性或修改属性以下特性(writable, configurable, enumerable)的行为将被无效化,默认为 false。

        enumerable 是否能在for...in循环中遍历出来或在Object.keys中列举出来。默认为 false。

    Example:
        var obj = {};
        Object.defineProperty(obj, 'name', {
            get: function(){
                debugger;
                // this.name;  
                return 23;
            },
            set: function(newValue){
                debugger
            }
        })

        Object.defineProperty(obj, 'sex', {
            get: function(){
                debugger;
                return '女';
            },
            set: function(newValue){
                debugger
            }
        })

        obj.name = 'sss';           // 调用set()
        console.log(obj.name);      // 调用get()   23

        obj.sex = '男';
        console.log(obj.sex);       // 女


    MVVM的核心: 

        <div>
            <p>你好,<span id='nickName'></span></p>
            <div id="introduce"></div>
        </div>

        <script type="text/javascript">
            // 视图控制器
            var userInfo = {};
            Object.defineProperty(userInfo, "nickName", {
                get: function(){
                    return document.getElementById('nickName').innerHTML;
                },
                set: function(nick){
                    document.getElementById('nickName').innerHTML = nick;
                }
            });

            Object.defineProperty(userInfo, "introduce", {
                get: function(){
                    return document.getElementById('introduce').innerHTML;
                },
                set: function(introduce){
                    document.getElementById('introduce').innerHTML = introduce;
                }
            })

            userInfo.nickName = "siguang";
            userInfo.introduce = "我是"+ userInfo.nickName +",我来自黑龙江,..."
        </script>

    https://segmentfault.com/a/1190000004346467


12、Object.defineProperties: 与defineProperty相同就是可以设置多个属性

    let book = { year: 2004, edit: 1}
    Object.defainProperyies(book, {
        year:{
            get: function(){},
            set: function(){}
        },
        edit: {
            get: function(){},
            set: function(){}
        }
    })


13、Object.getPrototypeOf(object): 调用父类原型上的方法

    // 定义一个父类
    function PersonA(){
        this.methodA = function(){ 
            alert("a");
        }
    }
    PersonA.prototype.methodB = function(){
        alert('b');
    }

    // 定义一个子类
    function Man(){
        this.m1 = function(){
            //getPrototypeOf只有继承父类的时候才可以调用其方法
            Object.getPrototypeOf(this).methodA();        
        }
    }

    Man.prototype = new PersonA();
    Man.prototype.m2 = function(){
        Object.getPrototypeOf(this).methodB();
    }

    var man = new Man();
    man.m1();        // a
    man.m2();        // b


14、Object.keys(obj): 将对象obj下所有的属性的key,返回一个数组,用可以用它来判断是数组是否为空

    Object.keys(obj).length 是否等于0

15、Object.getOwnPropertyDescriptor():     

Date对象

var od = new Date();    // 创建当前中国标准时间 Thu Apr 27 2017 18:39:17 GMT+0800 (CST)
var od = new Date('2017-04-27 18:40:00');   // 指定时间 返回当前标准时间 Thu Apr 27 2017 18:40:00 GMT+0800 (CST)

1、getTime(): 返回当前毫秒数

2、setTime(): 以毫秒设置时期

    var od = new Date(); 
    od.setTime(12312312312332); 
    console.log(od);        // Mon Feb 29 2360 22:45:12 GMT+0800 (CST)

3、getFullYear()、setFullYear(): 获取或设置年份

4、getMonth()、setMonth(): 获取或设置月份,值需要+1

5、getDate()、setDate(): 获取或设置日

6、getDay(): 返回星期几,值是0-6

7、getHours(): 小时

8、getMinutes(): 分钟

9、getSeconds(): 秒

Number对象

1、toFixed(): 将值格式化小数点后几位

String对象

1、length: 字符串长度

2、charAt(): 返回指定位置的字符  'abcde'.charAt(3)  'd'

3、chartCodeAt(): 返回指定位置的字符编码

4、concat(): 两个字符串拼接

5、split(): 将字符串以什么为分割,并返回为一个数组

截取

6、slice(begin,end): 截取字符串指定开始和结束位置的字符并返回, 可以接受负数

7、substring(begin,end): 截取字符串从开始到结束,

8、substr(begin, length): 返回一个指定开始到一个结束长度的字符

位置

9、indexOf(): 查找指定字符所在的位置

10、lastIndexOf(): 从后向前查找指定字符的位置

11、trim(): 删除前后空格  str.replace(/^\s*|$\s*/g, '');

12、toLocaleUpperCase(): 转成小写字母

13、toUpperCase(): 转成大写字母

正则

14、search(reg): 搜索正则中匹配字符的位置,没有返回-1

15、match(reg): 将匹配的正则返回一个数组

    let text = "cat, bat, sat, fat";
    let om = text.match(/.at/g);        // ["cat", "bat", "sat", "fat"]

16、exec():

17、replace(reg, 替换字符): 替换指定字符

Math

1、min()、max(): 返回最小、最大值

舍入

2、ceil(): 向上舍入

3、floor(): 向下舍入

4、round(): 四舍五入

5、random(): 随机数 0-1之间

6、abs(): 绝对值

7、sin()、cos()

Global对象

encodeURI()、encodeURIComponent()

前端动画实现种类

1、纯粹的CSS3: transition/animation+transform(animate.css)

2、JS+CSS3 transition或者animation: 这里第一种一样,只是通过js里add class和remove class去增加或者移除对应的动画

3、纯粹JS控制时间轴: 第一和第二种都是自带时间轴,使用 setInterval / setTimeout / requestAnimationFrame 不断地修改 DOM 的 style 属性产生动画

整理

1、==、===

    '100' == 100;     // true;    undefined == null; 因为JS会将两个值转换为相同类型
    '100' === 100;     // false

    == 是先将数值转换后在进行比较,JS的一个设计缺陷、 === 不转换数值进行比较


2、 while和do...while 

    do...while 不管条件是否成立都会执行一次
    var cont = 0;
    do{
        cont++;
        console.log(cont);                // 1;
    }while(cont > 10);


3、break 退出循环、continue 退出当前循环开始下一循环

| http://kangax.github.io/compat-table/es5/ ES5兼容表
| https://developer.mozilla.org/zh-CN/docs/Web/API/Element/className API
| https://segmentfault.com/a/1190000000515151
| https://segmentfault.com/a/1190000005653355
| https://msdn.microsoft.com/zh-cn/library/dn342818(v=vs.94).aspx
| http://www.alloyteam.com/2016/05/javascript-timer/ js运行机制

设计模式

| 面向对象(类型判断、封装、多态、闭包、高阶函数)
| 单例模式 - 命名空间、只被实例化一次
| 工厂模式 - 加工在输厂的过程
| 外观模式 - 将复杂的接口统一,用于低层兼容
| 适配器模式 - 将一个接口转化为另一个接口
| 代理模式 - 一个对象不能直接访问另一个对象时,使用代理对象
| 装饰者模式 - 不改变原有对象的,并对其进行拓展
| 桥接模式 - 提取公用的方法,并通过桥接来进行连接
| 享元模式 -
| 观察者模式 -
| 状态模式 -
| 访问者模式 -
|
| 组合模式
| 策略模式 - 将一组算法封装起来,使其可以相互之间替换
| 中介者模式

类型判断

只能将带有duckSinging()方法的对象加入到 choir 数组中

<script>

    // 方法一
    var duck = {
        duckSinging: function(){
            console.log('嘎嘎嘎');
        }
    }

    // 方法二
    var chicken = {
        chicken: function(){
            console.log('嘎嘎嘎');
        }
    }

    // 存储带有duckSinging()方法的对象
    var choir = [];

    var joinChoir = function(animal){
        if(animal && typeof animal.duckSinging == 'function'){        // 只能加入带有duckSinging()方法的对象
            choir.push(animal);
            console.log('恭喜入合唱团');
            console.log('合唱团已有成员数量', choir.length);
        }
    }

    joinChoir(duck);
    joinChoir(chicken);

</script>

封装

封装: 目的是将信息隐藏, 其它语言通过private、public、protected来处理访问权限

js没有这些关键字通过变量的作用域来实现封装

<script>
    var Book = funtcion(id, bookname, price){
        // 私有属性
        var name = 1;

        // 私有方法
        function checkId(){ }

        // 公有属性
        this.id = id;
        this.bookname = bookname;

        // 公有方法
        this.copy = function(){}

        // 特权方法
        this.getName() = function{ return name }
    }

    // 在原型 (prototype) 来添加属性和方法,有两种方式
    // 1、为原型一一添加属性和方法
    // 2、将一个对象赋给原型

    Book.prototype.display = function(){
        // 展示这本书
    }

    Book.prototype = {            // 这种方法会将prototype下的constructor被覆盖掉
        display: function(){
            // 展示这本书
        }
    }
</script>

<script>
    // 闭包实现 1
    var Book = (function(){
        // 静态私有变量
        var bookNum = 0;

        // 静态私有方法
        function checkBook(name){}

        // 返回构造函数
        return function(newId, newName, newPrice){
            var name, price;
            function checkId(name){}
        }
    });

    Book.prototype = {
        isJSBook: false,
        display: function(){}
    }


    // 闭包实现 2
    var Book = (function(){

        // 私有变量
        var bookNum = 0;

        // 私有方法
        function checkBook(name){ }

        // 创建类
        function _book(newId, newName, newPrice){}
        _book.prototype = {}

        return _book
    })();
</script>

继承

一、类式继承

    将父类的实例赋给子类的原形,类式继承的原因: 类的原型对象作用就是为类的原型添加公有方法,但不能直接访问这些属性和方法,必须通过原型prototype来访问

    <script>

        // 父类
        function Parent(){
            this.name = 'siguang'
        }

        Parent.prototype.say = function(){ 
            console.log(this.name);
        }

        // 子类                
        function Childer(){}

        Childer.prototype = new Parent();   // 类式继承

        // 上一步执行后prototype的constructor会指向Parent,因为constructor指向还是在Paremt类上
        Childer.prototype.constructor = Childer;

        Childer.prototype.getSubValue = function(){
            console.log('getSubValue')
        }

        // 实例
        var oParent = new Parent();
        var oChilder = new Childer();

        oParent.say();                // siguang
        oChilder.say();                // siguang
        console.log(oChilder.name); // siguang
        oChilder.name = 'haha';
        oChilder.say();                // haha
        oChilder.getSubValue();        // getSubValue
    </script>


二、构造函数式继承

    /*
    * 构造函数继承
    * 继承非prototype下的属性和方法
    */
    <script>
        // 父类继承
        function SuperClass(id){
            this.books = ['javascript', 'html', 'css'];
            this.id = id;
            this.showId = function(){
                console.log(this.id);
            }
        }
        SuperClass.prototype.showBooks = function(){
            console.log(this.books);
        }

        // 声明子类
        function SubClass(id){
            // 继承父类所有公用属性和方法(this下的内容),但不继承prototype下的属性和方法
            SuperClass.call(this, id);
        }

        // SubClass.prototype.constructor = SubClass;

        var sub1 = new SubClass(10);
        var sub2 = new SubClass(20);

        sub1.books.push('设计模式');    
        console.log(sub1.books);        // ['javascript', 'html', 'css', '设计模式']
        console.log(sub1.id);            // 10
        // sub1.showBooks();            // 报错,不
        sub1.showId();                    // 10

        console.log(sub2.books);        // ['javascript', 'html', 'css']
        console.log(sub2.id);            // 20
    </script>


总结: 类似继承与构造函数式继承的区别

    1、类似继承: ChildreClass.prototype = new ParentClass();

        继承父类的公用属性和方法(this.的内容)和 prototype下的属性和方法, 需要改变constructor的名字

    2、构造函数式继承: ParentClass.call(this);

        只能继承公用属性和就去,不能继承父类prototype下的属性和方法, 不需要改变constructor的名字


三、原型继承

    通过一个继承方法,创建一个过渡对象,将继承的父对象赋给过渡对象的原型,在返回过渡对象的实例

    <script>
        var Parent = function(){
            this.blod = 20;
            this.level = 1;
        }
        Parent.prototype.getBlod = function(){
            console.log(this.blod, this.level);
        }

        Object.create = Object.create || function(obj){
            var F = function(){};        // 声明一个过渡对象
            F.prototype = obj;            // 过渡对象的原型继承父对象
            return new F();                // 返回过渡对象的一个实例,该实例的原型继承了父对象
        }

        var oParent = new Parent();
        var oChilde = Object.create(oParent);

        oChilde.blod = 30;    // 如果clone不设置blod属性,会到prototype的指向中找,最终会在oParent中找到属性
        oChilde.getBlod();    // 30 1

        oParent.getBlod();    // 20 1
    </script>


四、寄生式继承

    就是将原型继承在二次封装,并返回一个对象

    <script>

        // 寄生式继承
        // 声明基对象
        var book = {
            name: 'js book',
            alikeBook: ['css book', 'html book']
        }

        function createBook(obj){
            // 通过原型继承方式创建新对象
            var o = new inhreitObject(obj);
            // 拓展新对象
            o.getName = function(){
                console.log(this.name);
            }

            // 返回拓展新对象
            return o;
        }

        function inhreitObject(obj){
            var F = function(){};
            F.prototype = obj;
            return new F();
        }


        var oCreateBook = createBook(book);
        oCreateBook.getName();            // 'js book'

    </script>


五、多继承

    只适用于对象,不适用构造函数,继承某一个类,和继承多个类

    <script>

        // 单继承 属性复制
        // 这种是浅复制,象jquery等框架实现了深度复制
        var extend = function(target, source){
            // 遍历源对象中的属性
            for(var property in source){
                // 将源对象中的属性复制到目标对象中
                target[property] = source[property];
            }

            // 返回目标对象
            return target;
        }


        var book = {
            name: 'javascript 设计模式',
            alike: ['css', 'html', 'javascript'],
            type: {
                name: '计算机',
                money: 20
            }
        }
        var anotherBook = {
            color: 'blue'
        }

        extend(anotherBook, book);
        console.log(anotherBook.name);
        console.log(anotherBook.alike);
        console.log(book, anotherBook);



        // 多继承 多个对象继承 属性复制
        var mix = function(){
            var i = 1,                    // 从第二个参数起为被继承的对象
                len = arguments.length,    // 获取参数长度
                target = arguments[0],    // 第一个对象为目标对象
                arg;                    // 缓存参数对象

            // 遍历被继承的对象
            for(; i<len; i++){
                // 缓存当前对象
                arg = arguments[i];
                // 遍历被继承对象中的属性
                for(var property in arg){
                    // 将被继承对象中的属性复制到目标对象中
                    target[property] = arg[property];
                }
            }
            return target;
        }


        var book1 = {
            name: 'javascript 设计模式',
            alike: ['css', 'html', 'javascript'],
            type: {
                name: '计算机',
                money: 20
            }
        }

        var book2 = {
            tag: '书'
        }

        var book3 = {
            detail: '产品优势'
        }

        var newBook = mix(book1, book2, book3);

    </script>

多态

多态: 就是调用同一对象,通过参数发出不同指令,执行不同的结果

<script>

    var googleMap = {
        show: function(){
            console.log('开始渲染谷歌地图');
        }
    }

    var baiduMap = {
        show: function(){
            console.log('开始渲染百度地图');
        }
    }

    // 渲染地图
    var renderMap =  function(map){

        // 如果对象下有show方法就执行
        if(map.show instanceof Function){        
            map.show();
        }

        // 另一个判断类型模式
        // if(map && typeof map.show == 'function'){
        //     map.show();
        // }
    }

    renderMap(googleMap);
    renderMap(baiduMap);

</script>

闭包、高阶函数

高阶函数至少满足以下条件之一

一、函数可以作为参数被传递

    <script>
        var getUserInfo = function(userId, callback){
            $.ajax('http://xx.com/user?uid='+userId, function(data){
                if(typeof callback == 'function'){
                    callback();
                }
            })
        }
    </script>

二、函数可以作为返回值输出

    <script>

        // 函数作为返回值输出
        var isType = function(type){
            return function(obj){
                return Object.prototype.toString.call(obj) === '[object '+ type +']'
            }
        } 

        var str = "sdfsdf"
        var isString = isType('String');
        console.log(isString(str));        // true
    </script>

全局变量的解决方法

避免全局函数: 1、对象方法   2、函数对象    3、构造函数

<script>

    // 都是全局变量
    function checkName(){
        // 验证姓名
    }

    function checkEmail(){
        // 验证邮箱
    }

    function checkPassword(){
        // 验证密码
    }

    /*
    * 方法一 对象收编全局变量
    */
    var ChceckObject = {
        checkName: function(){
            // 验证姓名
        },
        checkEmail: function(){
            // 验证邮箱
        },
        checkPassword: function(){
            // 验证密码
        }
    }


    /*
    * 方法二 函数对象
    */
    var CheckObject = function(){
        return {
            checkName: function(){
                // 验证姓名
            },
            checkEmail: function(){
                // 验证邮箱
            },
            checkPassword: function(){
                // 验证密码
            }
        }
    }

    // 调用
    var oCheck = CheckObject();
    oCheck.checkName();


    /*
    * 方法三 构造函数写法
    */
    var CheckObject = function(){
        this.checkName = function(){
            // 验证姓名
        }
        this.checkEmail = function(){
            // 验证邮箱
        }
        this.checkPassword = function(){
            // 验证密码
        }
    }

</script>

/* 创建型模式 */

单例模式

单例模式: 又被称为单体模式,只允许实例化一次的对象类

全局变量 var a = {};    属于单例对象, 不属于单例模式

jquery就是一个很大的单例,js载入时被初始化一次

    (function(){
        var jquery = (function(){})();
        window.jQuery = window.$ = jQuery;
    })(window);


一、最简单的单例就是一个对象

    var app = {
        util: {},
        tool: {},
        ajax: {}
    }


二、私有变量的单例模式,减少全局变量方法

    1、使用命名空间

        var MyApp = {};

        MyApp.namespace = function(name){
            var parts = name.split('.');
            var current = MyApp;
            for(var i in parts){
                if(!current[parts[i]]){
                    current[parts[i]] = {}
                }
                current = current[parts[i]];
            }
        }

        MyApp.namespace('event');
        MyApp.namespace('dom.style');


    2、使用闭包封装私有变量

        var user = (function(){
            var _name = 'sven',
                _age = 30;

            return {
                getUserInfo: function(){
                    return _name +'-'+ _age;
                }
            }
        })();


三、惰性单例模式

    <script>

        // 惰性单例模式  只有在需要的时候才会创建
        var createLoginLayer = (function() {
            var div;
            return function() {
                if (!div) {
                    div = document.createElement('div');
                    div.className = 'dialog';
                    div.innerHTML = '我是登录窗口';
                    div.style.display = 'none';
                    document.body.appendChild(div);
                }

                return div
            }
        })();

        var oLoginBtn = document.querySelector('#loginBtn');
        oLoginBtn.onclick = function(){
            var oLayer = createLoginLayer();
            oLayer.style.display = 'block';
        }

    </script>

工厂模式

工厂模式: 将不同的参数传入到工厂方法中,进行加工后,然后在返回新的产品

// 创建一个工厂函数,并将结果返回
function createPerson(name, age, sex){
    var createObject = {};

    // 加工
    createObject = {    
        name: name,
        age: age,
        sex: sex,
        showInfo: function(){
            console.log('姓名:'+ this.name +"  年龄:" + this.age);
        }
    }

    // 返回成品
    return createObject;
}

var person = createPerson('siguang', 30, '男');
person.showInfo();

建造者模式 builder

将一个复杂对象的构建层与表示层相互分离

原型模式 prototype

用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性及方法

<script>

    // 定义一个基本的图片轮播对象
    var LoopImages = function(imgArr, container){
        this.imgArr = imgArr;
        this.container = container;
    }
    LoopImages.prototype = {
        // 创建
        createImage: function(){
            console.log('loopImage createImage function');
        },
        // 切换方法
        changeImage: function(){
            console.log('LoopImage changeImage function');
        }
    }

    // 定义一个上下滑动的效果
    var SliderLoopImage = function(imgArr, container){
        LoopImages.call(this, imgArr, container);
    }
    SliderLoopImage.prototype = new LoopImages();            // 就是类似继承,并将要改变的方法重写

    // 重写切换方法
    SliderLoopImage.prototype.changeImage = function(){
        console.log('SlideLoopImg changeImage function');
    }

    var oSlider = new SliderLoopImage(['1.jpg', '2.jpg'], '#box');
    oSlider.createImage();
    oSlider.changeImage();

</script>

/* 结构型模式 */

外观模式

外观模式: 为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易

// 外观模式实现
function addEvent(dom, type, fn){
    if(dom.addEventListener){
        dom.addEventListener(type, fn, false);
    }
    else if(dom.attachEvent){
        dom.attachEvent('on'+type, fn);
    }
    else{
        dom['on'+type] = fn;
    }
}

var myInpurt = document.querySelector('#myinput');

addEvent(myInpurt, 'click', function(){
    console.log('绑定第一个事件')
})

适配器模式

适配器模式: 将一个类的接口转化成另外一个接口,使类之间的接口不兼容问题通过适配器得以解决

一、如果有jQuery框架,现在A框架与jQuery框架基本相同可以将两种框架适配

    // 定义A框架
    var A = jQuery || {};

    A.g = function(id){
        return document.getElementById(id);
    }

    A.on = function(id, type, fn){
        var dom = typeofi id === 'String' ? A.g(id) : id;
        if(dom.addEventListener){
            dom.addEventListener(type, fn, false);
        }
        else if(dom.attachEvent){
            dom.attachEvent('on'+type, fn);
        }
        else{
            dom['on'+type] = fn;
        }
    }

二、jquery适配器

    window.A = A = jQuery;

三、参数适配

    function doSomeThing(obj){
        var adapter = {
            name: '雨夜',
            titel: '设计',
            age: 30,
            color: 'pink',
            size: 100,
            prize: 50
        }

        for(var key in adapter){
            adapter[key] = obj[key] || adapter[key];        // 处理如果obj没有的参数
        }
        return adapter;            // 也可以使用extend();
    }

代理模式

代理模式: 由于一个对象不能直引用另一个对象,所以需要一个代理对象来为两个对象之间起到中介作用

<script>
    var Flower = function(){};

    var xiaoming = {
        sendFlower: function(target){
            var flower = new Flower();
            target.receiveFlower(flower);
        }
    }

    // B代理小明去给A送花
    var B = {
        receiveFlower: function(flower){
            A.listenGoodModd(function(){        // 侦听A的心情
                A.receiveFlower(flower);
            })
        }
    }

    // A接收小明的花
    var A = {
        receiveFlower: function(flower){
            console.log('收到花'+ flower);
        },
        listenGoodModd: function(fn){
            setTimeout(function(){
                fn()
            }, 10000);
        }
    }

    xiaoming.sendFlower(B);
</script>

装饰者模式

装饿者模式: 在不改变原对象的基础上,通过对其进行包装拓展(添加属性或方法)使原有对象可以满足用户的更复杂需求

<p>姓名: <input type="text" name="" id="username" /><span id="usernameError">Error username xxxx</span><br></p>
<p>密码: <input type="text" name="" id="password" /><span id="passwordError">Error password xxxx</span></p>

<script>

    /*
    * 装饰者模式: 在不改变原对象的基础上,通过对其进行包装拓展(添加属性或方法)使原有对象可以满足用户的更复杂需求
    */

    // 点击文本框,显示提示信息,并保留原input上的事件
    var username = document.querySelector('#username');
    var password = document.querySelector('#password');

    // 基础需求,点击文本框后会加入文本内容
    username.onclick = function(){
        this.value = '初始化username';
    }.bind(username);

    password.onclick = function(){
        this.value = '初始化password';
    }.bind(password);


    // 新增的需求,点击后需要有提示消息,这里不破坏原有的功能
    // 装饰者方法
    var decorator = function(input, fn){
        var input = document.querySelector(input);

        // 判断事件是否已经绑定事件
        if(typeof input.onclick == 'function'){
            // 缓存input本身的处理的事件
            var oldClickFn = input.onclick;

            // 为事件定义新的事件, 执行将新好的方法全执行
            input.onclick = function(){
                oldClickFn();
                fn();
            }
        }
        else{
            input.onclick = fn;
        }
    }

    // 调用
    decorator('#username', function(){
        document.querySelector("#usernameError").style.display = 'block';
    })
    decorator('#password', function(){
        document.querySelector("#passwordError").style.display = 'block';
    })

</script>

桥接模式

桥接模式: 将一个功能有共用的部分抽取出来,将实现与抽出来共用方法,通过桥接方法链接在一起,这就是桥接模式

<div class="box">
    <span>最新回答</span>
    <span>热门回答</span>
    <span>等待回答</span>
</div>

<script>
    var box = document.querySelector('.box');
    var spans = box.getElementsByTagName('span');

    // 抽出的公用
    function changeColor(dom, color, bg){
        dom.style.color = color;
        dom.style.backgroundColor = bg;
    }

    // 桥接模式
    function bindSpan(){
        var i = 0;
        var len = spans.length;

        for(i; i<len; i++){
            spans[i].onmouseover = function(){
                changeColor(this, '#ad2102', '#ffbb96');
            }
            spans[i].onmouseout = function(){
                changeColor(this, '#ad2102', '#fff2e8');
            }                
        }
    }

    bindSpan();
</script>

享元模式

享元模式: 运用共享技术有效地支持大量细粒的对象,避免对象间有相同内容造成多余的开销

/* 行为型设计模式 */

观察者模式

观察者模式 - 又称发布订阅模式或消息机制

状态模式

状态模式 - 当一个对象内部状态发生改变时,会导致行为改变

状态模式是解决程序中臃肿的分支判断语句问题,将每个分支转化一种状态独立出来

<script>

    // 创建一个玛丽类
    var MarryState = function(){

        // 存储内部状态
        var _currentState = {};

        // 动作与状态方法映射
        var states = {
            jump: function(){
                console.log('jump');
            },
            move: function(){
                console.log('move');
            },
            shoot: function(){
                console.log('shoot');
            },
            squat: function(){
                console.log('squat');
            }
        };

        // 动作控制类
        var Action = {

            // 改变状态方法
            changeState: function(){
                var arg = arguments;
                _currentState = {};
                if(arg.length){
                    for(var i=0, len=arg.length; i<len; i++){
                        _currentState[arg[i]] = true;
                    }
                }
                return this;
            },

            // 执行动作
            goes: function(){
                console.log('触发一次动作');
                for(var i in _currentState){
                    states[i] && states[i]();       // 如果动作存在并执行
                }
                return this;
            }
        }

        return {
            change: Action.changeState,
            goes: Action.goes
        }
    }


    MarryState()
        .change('jump', 'shoot')
        .goes()

</script>

策略模式

策略模式: 定义一系列算法,把他们封装起来,并使它们可以相互替换

策略模式由两部分组成:

    1、策略类,策略类封装了具体的算法,并负责具体的计算过程

    2、环境类,接受客户的请求,把请求委托给一个策略类

Example:

    <script>
        // 需求根据KPI等级返回奖金金额

        // 定义策略类
        var strategies = {
            'S': function(salary){
                return salary * 4;
            },
            'A': function(salary){
                return salary * 3;
            },
            'B': function(salary){
                return salary * 2;
            }
        }

        // 环境类
        var calculateBonus = function(level, salary){
            return strategies[level] && strategies[level](salary);
        }

        console.log(calculateBonus('B', 2000));        // 4000
        console.log(calculateBonus('S', 5000));        // 20000

    </script>

职责链模式

职责链模式 - 解决请求的发送者与请求的接受者之间的耦合

命令模式

命令模式 - 将请求与实现解耦并封装成独立对象,从而使不同的请求对客户端的实现参数

迭代器模式

迭代器模式: 提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部

<script>
    var isType = function(type){
        var callType =  Object.prototype.toString.call(type);

        switch(callType){
            case '[object Object]':
                return 'object';
                break;

            case '[object Array]':
                return 'array';
                break;

            default: 
                return false;
                break;
        }
    }

    var each = function(arr, callback){
        if(isType(arr) == 'object'){
            for(var key in arr){
                callback.call(arr[key], key, arr[key]);
            }
        }
        else if (isType(arr) == 'array'){
            for(var i=0; i<arr.length; i++){
                callback.call(arr[i], i, arr[i]);
            }
        }
    }

    each([1, 2, 3], function(index, val){
        console.log(index, val);
    })

    each({name: 'siguang', age: 32, sex: '男'}, function(key, val){
        console.log(key, val);
    })
</script>

发布订阅模式模式

发布订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变,所有依赖于它的对象都将得到通知.

js中事件模型来替代传统的发布订阅模式

| http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html

React Native之基础篇

React Native 介绍

一、Native的类别

    React Native 编译后是原生应用,v0.22.0热更新hot reloading

    Hybrid  混合应用

    phoneGap 包皮应用,一次编写,到处运行,依然是网页,只是将页面内容内嵌到webView中,用中间件来对网页进行通信,对一些动画会有性能上的问题


二、实时加载(Live Reload)和热加载(Hot Reload)的区别

    http://www.jianshu.com/p/1fa6e9c0799f

    Enable Live Reload  实时加载,应用于更新时需要刷新当前页面,可以看到全局刷新效果

    Enable Hot Reloading   热加载,当布局修改时会自动更新模拟器,看不出来刷新效果类似买局部刷新

三、React Native 应用部署/热更新 codePush

    http://blog.csdn.net/fengyuzhengfan/article/details/52003798

安装

1、安装 XCode

    $ xcode-select --install  检查xcode是否安装, 如果未安装会出现提示

    android 下载 android studio  https://developer.android.google.cn/index.html


2、安装 homebrew

    用于包管理,与npm类似

    $ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

    $ sudo chown -R `whoami` /usr/local   解决/usr/local目录不可写的权限问题  

    Homebrew将工具安装到 /usr/local/Cellar 目录中,并在 /usr/local/bin 中创建符号链接。


3、安装 watchman 和 flow

    watchman是facebook的开源项目用于监视文件并且记录文件的改动情况

    flow 是js的静态类型检查器,用于找出js代码中的类型错误

    $ brew install watchman

    $ brew install flow


4、安装 NodeJS

5、安装 react-native 

    $ npm install -g react-native-cli      // Yarn是Facebook提供的替代npm的工具,可以加速node模块的下载

6、vscode中react-native插件

初始化项目

1、创建项目

    $ react-native init 项目名  // 创建项目

    $ react-native run-ios     // 运行 react-native run-ios --simulator "iPhone 4s"  定义模拟器类型

        或者在ios目录 AwesomeProject.xcodeproj  双击打开


2、查看命令

    $ react-native -h   所有命令

    $ react-native -v   版本


3、安装第三方插件

    $ npm i react-native-elements lodash query-string sha1 react-native-audio react-native-video react-native-image-picker react-native-progress react-native-sk-countdown react-native-swiper react-native-barcodescanner --save


4、link 命令

    link的原因:以下组件都是原生开发,wrapper了一层js,因此需要link .a到project中

    $ react-native link

    或 rnpm link     需要先安装rnpm     npm install rnpm -g --save-dev


5、模拟器调试技巧

    http://blog.csdn.net/quanqinyang/article/details/52215652  

    # 模拟器打开后可以通过cmd+1/2/3/4来调整窗口大小

    # 模拟器在所有窗口置顶 window -> stay in front

    # ISO cmd + D 打开调试菜单,Android cmd + M

    # comond + T  show Animate 呼出菜单cmd+D会变成慢动画


    # Reload 重新bundle代码 cmd + R

    # Debug JS Remotely   调试模式 chrome Developer Tools调试

    # Enable Live Reload  实时加载,应用于更新时需要刷新当前页面,可以看到全局刷新效果

    # Enable Hot Reloading   热加载,当布局修改时会自动更新模拟器,看不出来刷新效果类似买局部刷新


    # 警告

        红错误 - console.error('')

        关闭警告 - console.disableYellowBox = true;    显示警告 - console.warn('YellowBox is disabled.');

    # 日志 - react-native log-ios      react-native log-android

    # chrome开发工具 - debug js Remotely  可以跟进代码

react-native 目录

.
├── .DS_Store
├── .babelrc            // ES6转换的配置
├── .buckconfig
├── .flowconfig         // 做js代码类型检查 
├── .watchmanconfig     // 监听文件改变watchman的配置
├── .gitattributes
├── .gitignore          // 对哪些文件被git忽略不显示
├── node_modules        // 存储资源包    
├── __tests__
├── android             // android原生文件目录
├── ios                 // ios的原生文件目录 运行reactNative会将文件打包到这个目录,然后xcode调用的就是这里的项目文件
├── app.json
├── index.android.js    // android文件入口
├── index.ios.js        // ios文件入口
├── package.json        // 依赖文件
└── yarn.lock

AppRegistry 注册模块,用来告诉RN哪个组件被注册为根窗口

AppRegistry是js运行RN应用的入口,通过registerComponent()来注册方法

AppRegistry.registerComponent('项目名', () => 入口组件名)  注册入口

AppRegistry.runApplication 来真正运行应用

React Native 生命周期

第一阶段,初始化

    getDefaultProps -> getInitialState -> componentWillMount -> render -> componentDidMount

       获取配置参数        获取初始状态值         通知要开始渲染        渲染       告诉组件已经完成


第二阶段,运行阶段 组件运行中

    1、state变化 -> shouldComponentUpdate -> componentWhllUpdate ->  render -> componentDidUpdate

       状态变化    判断组件是否要更新true/false     需要更新就触发           渲染         更新组件

    2、props变化 -> componentWillReceiveProps -> shouldComponentUpdate -> componentWhllUpdate ->  render -> componentDidUpdate

       props变化         属性改变调用             判断组件是否要更新true/false       需要更新就触发        渲染           更新组件


第三阶段 卸载

    unmount -> componentWillUnmout -> 结束 

组件生命周期

props、state

一、props属性: 父组件传值给子组件

    <Greeting name='Rexxar' />      父组件调用子组件

    <Text>Hello {this.props.name}!</Text>   子组件接收

    1、defaultProps定义默认的props

        class Smiple extends Component{
            static defaultProps = {     // 定义默认props静态属性
                name: 'siguang'
            }

            static propsTypes = {       // 检测props的类型
                name: 'String'
            }

            render(){
                return (
                    <View>
                        <Text> {this.props.name} </Text>
                    <View>
                )
            }
        }


二、state状态、setState()改变状态,组件中可以改变的值

    export default class rrdProject extends Component {
        constructor(props){
            super(props);

            // 定义state对象
            this.state = { 
                showText: ''
            }
        }

        // state = {  };     // RN也支持ES7 类的静态属性写法

        render() {
            return(
                <View style={styles.container}>
                    <Text>这里有内容: {this.state.showText}</Text>
                </View>
            );
        }
    }

ref

通过ref来获取真实的DOM

import childComponent from './childComponent';

class Simple extends Component {
    clickChild(){
        var size = this.refs.childRef.getSize();       // 获取childComponent组件的getSize()方法
    }

    render() {
        return (
            <View>
                <Text>Simple 基本页面</Text>
                <button onPress={this.clickChild} title="点击" />

                <childComponent ref="childRef" />
            </View>
        )
    }
}

样式

http://blog.csdn.net/sbsujjbcy/article/details/50017029
http://www.cnblogs.com/wonyun/p/5481134.html

1、直接写样式

    <View style={{width: 193, height: 110}}></View>     {{}} 两个括号可以直接写样式
    <View style={styles.red}></View>                    {} 一个括号需要来调用样式类
    const styles = StyleSheet.create({
        red: {
            color: red
        }
    })

2、写多个样式

    <Text style={[styles.btn, styles.color]}>立即体验</Text>

    // 支持表达式
    <Text style={[styles.btn, styles.color && this.props.dotColor]}>立即体验</Text>


2、styleSheet.create({}) 定义样式

    const styles = StyleSheet.create({
        rootView:{
            height: '100%',
            width: '100%',
            backgroundColor: '#eff0f3'
        },
        big: {
            color: 'blue',
            fontSize: 30
        }
    })
    <View style={styles.rootView}>      // 多个样式 style={[styles.rootView, styles.big]}
        <Text>REACT NATIVE ELEMENTS</Text>
    </View>


3、颜色支持

    '#ccc'、 'rgba(0,0,0,.4)'、 'transparent'、 'red'


4、RN样式与css样式的异同

    View类型div,会默认占用窗口的100%宽度

    绝对定位和相对定位不需要父元素设置positioin,也没有zIndex配置

    不能将RN的inline元素设置maginTop、marginBottom

    样式继承只存在Text元素内的Text元素

        <Text style={{color:'red'}}>
             <Text>父:我是white还是red{'\n'}
                 <Text>子:那我是神马颜色</Text>
             </Text>
       </Text>

Flex布局

直接给组件指定宽、高   <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
http://www.devio.org/2016/08/01/Reac-Native%E5%B8%83%E5%B1%80%E8%AF%A6%E7%BB%86%E6%8C%87%E5%8D%97/#和而不同

一、父视图属性:

    1、flexDirection('row', 'column','row-reverse','column-reverse')- 布局子元素的排列方向,默认是column不是row

        <View style={{flex: 1, flexDirection: 'row'}}>
            <View style={{flex:1, height: 50, backgroundColor: 'powderblue'}} />
            <View style={{flex:2, height: 50, backgroundColor: 'skyblue'}} />
            <View style={{flex:3, height: 50, backgroundColor: 'steelblue'}} />
        </View>

        重要:  
            <View style={{flex: 1, flexDirection: 'row'}}>  
            父组件没设置flexDirection=row,默认布局为列,子组件设置flex:1是没用的,子组件只能设置width
            父组件设置为flexDirection=row,子组件可以设置flex:1

    2、flexWrap ('wrap', 'nowrap') - 定义子元素是否允许多行排列

    3、justifyContent ('flex-start', 'flex-end', 'center', 'space-between', 'space-around') - 定义子元素如何对齐

    4、alignItems ('flex-start', 'flex-end', 'center', 'stretch') - 定义子元素在侧轴对齐的


    justifyContent - 子元素沿主轴的排列方式

        justifyContent: flex-start、center、flex-end、space-around以及space-between
        <View style={{ flex: 1,  flexDirection: 'row' justifyContent: center}}>

    alignItems - 


二、子视图属性:

    1、alignSelf ('auto', 'flex-start', 'flex-end', 'center', 'stretch') - 

    2、flex - 

网络请求

RN里网络请求分为: Fetch、WebSocket、XMLHttpRequest

事件

onPress: 点击

onLongPress: 长按

maximumZoomScale和minimumZoomScale: 双指缩放

http://reactnative.cn/docs/0.42/panresponder.html

动画

1、LayoutAnimation 用于全局的布局动画

2、Animated 用于创建更精细的交互控制的动画

    Animated 封装了四个可以动画的组件: View、Text、Image和ScrollView

    start/stop 方法来控制动画按顺序执行

定时器

setTimeout, clearTimeout
setInterval, clearInterval
setImmediate, clearImmediate
requestAnimationFrame, cancelAnimationFrame

RN与原生通信

http://blog.csdn.net/zww1984774346/article/details/71167775

rn与IOS原生通信的三部分

    1、属性        2、原生模块      3、原生UI组件封装

    原生要写到AppDelegate.m文件中

    # 属性是最简单的跨组件通信,从原生组件传递属性到React Native 或 React Native到原生组件

        原生中添加imageList:

            NSArray *imageList = @[@"https://facebook.github.io/react/img/logo_og.png",
                        @"https://facebook.github.io/react/img/logo_og.png"];

            NSDictionary *props = @{@"images" : imageList};

            RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                        moduleName:@"AwesomeProject"
                                        initialProperties:props             // 这里initialProperties:props]传递给RN
                                        launchOptions:launchOptions];

        RN中接收与props传值一样:

            <View>
                {
                    this.props.images.map(function(items){
                        return <Image 
                            source={{uri:items}} 
                            style={{width:100,height:100}}></Image> 
                    })
                }
            </View>


1、RN访问OC

    // 创建原生模块实例
    var NativeModule = require('react-native').NativeModules.NativeTest;

    // 调用原生的doSomething()方法
    NativeModule.doSomething('ReactNative');


2、OC访问RN

http://www.jianshu.com/p/9d7dbf17daa5

生成测试包

iOS—最全的真机测试教程   http://www.cocoachina.com/ios/20160711/17004.html

团队开发的Xcode配置和生成包

    xCode -> Preferencse -> Accounts -> + 填加 选择 add apple ID 将账号和密码输入

    点击工程目录 -> General 
        -> Identity面板下的 Bundle Identifler 填写权限 “com.ucredit.paydayloan” 
        -> 在 Signing面板中的 Team 中选择"ZhongChengXingyu of......"

    将手机与mac连接,将Device选择当前手机设备,点击 运行,写读取设备成功后,在运行一次这次是执行build

原生组件

两种方法加载原生组件

1、react-native link 命令

    不仅会将第三方模块的原生组件代码链接入 Android/IOS 中,还会将字体等文件移动相应的目录中

2、通过Xcode来导入组件

    http://www.cnblogs.com/shaoting/p/6148085.html

3、Flow

    Flow是 Facebook出品的表态类型语言,可以将RN内部也支持ES 7的类属性的写法

        // 就可以不用在象ES 6将静态属性写到constructor中
        class MyComponent extends Component {
            constructor(props){
                super(props);

                // 私有属性
                this.isField = 1;   
                // state
                this.state = {
                    username: 'siguang'
                }
            }

            render(){
                return (
                    <View>
                        {this.username}
                    </View>
                )
            }
        }

        class MyComponent extends Component {
            isField = 1;
            state = {
                username: 'siguang'
            }

            render(){
                return (
                    <View>
                        {this.usernmae}
                    </View>
                )
            }
        }

调试

1、Command+R  重新刷新

2、Command+D  打开菜单 

3、Debug JS Remotely 用chrome浏览器调试,Alt+Command+j出现浏览器debug窗口

4、Disable Live Reload 时实刷新,代码修改保存后会就刷新

5、show Perf Monitor 打开FPS监控器

6、show Inspector 用于查看页面结构及属性

XCode装证书
http://www.cocoachina.com/ios/20160711/17004.html

| 相关文章
| https://github.com/jondot/awesome-react-native#videos
| http://reactnative.cn/docs/0.44/getting-started.html
| http://www.devio.org/
| https://github.com/crazycodeboy/RNStudyNotes/
| http://blog.csdn.net/quanqinyang/article/details/52215652 调试方法
| http://lib.csdn.net/base/reactnative/structure
| http://www.jianshu.com/p/5b185df2d11a
| http://www.lcode.org/react-native/
| http://blog.csdn.net/column/details/reactnative2016.html?&page=3
| http://lib.csdn.net/article/reactnative/63268 打包到真机
|
| 示例
| https://github.com/react-native-community
| https://github.com/ljunb/react-native-iShiWuPai 示例
| https://github.com/sunnylqm
| https://github.com/DoctorQ/react-native-helloworld
|
| http://blog.csdn.net/liu__520/article/category/6460088
| http://www.devio.org/tags/#React Native
|

微观经济学

什么是经济

经济 - 管理一个家庭的人

稀缺性 - 社会资源的有限性

经济学 - 研究社会如休管理自己的稀缺资源

经济学的十大原理

一、人们面临权衡取舍 - 要知道做一件事情得到了什么,又舍去了什么,什么都想要最后确什么都没有

绝对优势、比较优势

比较优势说明每种物品应该由生产这种物品成本较低的国家生产

进口、出口

进口: 在国外生产在国内销售的物品叫进口

出口: 在国内生产而在国外销售的物品称出口

成本机会

供给与需求

供给量是卖者愿意并且能够出售该物品的数量

供给定理是一种物品价格上升,该物品供给量增加,物品价格下降,物品供给量减少

过剩、短缺

过剩 - 当价格下降,供给者不能卖出他们想卖的所有物品

短缺 - 当前价格下,需求者不能买到他们想买的物品

市场

市场是由某种物品或服务的买者或卖者组成的一个群体,买者作为一个群体决定了一种产品的需求,而卖者作为一个群体决定了一个产品的代给

竞争

竞争市场有许多买者与卖者并且每

宏观经济学

宏观经济、微观经济

宏观经济 - 研究整体经济现象,包括通货膨胀、失业和经济增长

微观经济 - 研究家庭和企业如何做出决策,以及市场上的相互影响

GDP

国内生产总值即GDP,可以衡量经济中所有人总收

GDP = 消费 + 投资 + 政府购买 + 净出口

一、消费

    消费是家庭除购买住房之外用于物品与服务的支出

二、投资

    用于未来生产更多物品和服务的物品,如房产,这里投资与金融投资不同

三、政府购买 

    包括政府员工薪水与公务支出

四、净出口

    等于外国对国内生产的物品进行购买

CPI

消费物价指数 - 是普通消费者所购买的物品与服务总费用的衡量指标