分类: 技术

  • 如何理解多租户架构?(转)

      1.什么是多租户架构?
      2.多租户架构的优缺点?
      3.多租户架构的适用场景?

      让我们带着这几个问题进入下面的阅读。

    一、对多租户的理解

      多租户定义:多租户技术或称多重租赁技术,简称SaaS,是一种软件架构技术,是实现如何在多用户环境下(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。简单讲:在一台服务器上运行单个应用实例,它为多个租户(客户)提供服务。从定义中我们可以理解:多租户是一种架构,目的是为了让多用户环境下使用同一套程序,且保证用户间数据隔离。那么重点就很浅显易懂了,多租户的重点就是同一套程序下实现多用户数据的隔离。对于实现方式,我们下面会讨论到。

      在了解详细一点:在一个多租户的结构下,应用都是运行在同样的或者是一组服务器下,这种结构被称为“单实例”架构(Single Instance),单实例多租户。多个租户的数据是保存在相同位置,依靠对数据库分区来实现隔离操作。既然用户都在运行相同的应用实例,服务运行在服务供应商的服务器上,用户无法去进行定制化的操作,所以这对于对该产品有特殊需要定制化的客户就无法适用,所以多租户适合通用类需求的客户。那么缺点来了,多租户下无法实现用户的定制化操作。

      在翻阅多租户的资料时,还有一个名词与之相对应,那就是单租户SaaS架构(也被称作多实例架构(Multiple Instance))。单租户架构与多租户的区别在于,单租户是为每个客户单独创建各自的软件应用和支撑环境。单租户SaaS被广泛引用在客户需要支持定制化的应用场合,而这种定制或者是因为地域,抑或是他们需要更高的安全控制。通过单租户的模式,每个客户都有一份分别放在独立的服务器上的数据库和操作系统,或者使用强的安全措施进行隔离的虚拟网络环境中。因为本篇主要是讨论多租户,所以单租户的相关知识就简单了解一下,不做过多的阐述了。

    二、多租户数据隔离的三种方案

      在当下云计算时代,多租户技术在共用的数据中心以单一系统架构与服务提供多数客户端相同甚至可定制化的服务,并且仍可以保障客户的数据隔离。目前各种各样的云计算服务就是这类技术范畴,例如阿里云数据库服务(RDS)、阿里云服务器等等。

      多租户在数据存储上存在三种主要的方案,分别是:

      1. 独立数据库

      这是第一种方案,即一个租户一个数据库,这种方案的用户数据隔离级别最高,安全性最好,但成本较高。 
      优点: 
        为不同的租户提供独立的数据库,有助于简化数据模型的扩展设计,满足不同租户的独特需求;如果出现故障,恢复数据比较简单。 
      缺点: 
        增多了数据库的安装数量,随之带来维护成本和购置成本的增加。 
      这种方案与传统的一个客户、一套数据、一套部署类似,差别只在于软件统一部署在运营商那里。如果面对的是银行、医院等需要非常高数据隔离级别的租户,可以选择这种模式,提高租用的定价。如果定价较低,产品走低价路线,这种方案一般对运营商来说是无法承受的。

      2. 共享数据库,独立 Schema 
      这是第二种方案,即多个或所有租户共享Database,但是每个租户一个Schema(也可叫做一个user)。底层库比如是:DB2、ORACLE等,一个数据库下可以有多个SCHEMA 
      优点: 
        为安全性要求较高的租户提供了一定程度的逻辑数据隔离,并不是完全隔离;每个数据库可支持更多的租户数量。
      缺点: 
        如果出现故障,数据恢复比较困难,因为恢复数据库将牵涉到其他租户的数据; 
      如果需要跨租户统计数据,存在一定困难。

      3. 共享数据库,共享 Schema,共享数据表
      这是第三种方案,即租户共享同一个Database、同一个Schema,但在表中增加TenantID多租户的数据字段。这是共享程度最高、隔离级别最低的模式。 
      即每插入一条数据时都需要有一个客户的标识。这样才能在同一张表中区分出不同客户的数据。
      优点: 
        三种方案比较,第三种方案的维护和购置成本最低,允许每个数据库支持的租户数量最多。 
      缺点: 
        隔离级别最低,安全性最低,需要在设计开发时加大对安全的开发量; 数据备份和恢复最困难,需要逐表逐条备份和还原。

      如果希望以最少的服务器为最多的租户提供服务,并且租户接受牺牲隔离级别换取降低成本,这种方案最适合。 
        
      在SaaS实施过程中,有一个显著的考量点,就是如何对应用数据进行设计,以支持多租户,而这种设计的思路,是要在数据的共享安全隔离性能间取得平衡。

      因为我们用的底层库是MySQL,且要保证数据的完全隔离,所以用的方案属于第一种。独立数据库。因为MySQL下SCHEMA就是他的数据库名。所以每多服务一个用户,都需要新建一个数据库。如果是DB2或者是ORACLE的话,一个数据库下,可以采用独立的SCHEMA来进行数据隔离,这样会相对节省成本,且数据隔离的强度高。

    三、选择合理的实现模式 
      衡量三种模式主要考虑的因素是隔离还是共享

    成本角度因素 

        隔离性越好,设计和实现的难度和成本越高,初始成本越高。共享性越好,同一运营成本下支持的用户越多,运营成本越低。

      安全因素 

        要考虑业务和客户的安全方面的要求。安全性要求越高,越要倾向于隔离。

      从租户数量上考虑
        主要考虑下面一些因素 
        系统要支持多少租户?上百?上千还是上万?可能的租户越多,越倾向于共享。 
        平均每个租户要存储数据需要的空间大小。存贮的数据越多,越倾向于隔离。 
        每个租户的同时访问系统的最终用户数量。需要支持的越多,越倾向于隔离。 
        是否想针对每一租户提供附加的服务,例如数据的备份和恢复等。这方面的需求越多, 越倾向于隔离

      技术储备 
        共享性越高,对技术的要求越高。

      以上三部分内容分别针对开头的三个问题做了概要的阐述,文章中部分内容也是摘录自查阅的资料,实乃他人总结的非常好,所以就直接把轮子拿过来用了,旨在让你我更加了解多租户这种架构,还望勿喷!


    查阅资料如下:

       多租户和单租户SaaS的架构对比 http://blog.sina.com.cn/s/blog_a5ed66830102wddk.html
       数据层的多租户浅谈 https://www.ibm.com/developerworks/cn/java/j-lo-dataMultitenant/
       SaaS多租户数据隔离的三种方案 http://blog.csdn.net/yown/article/details/51288549

    转自:https://www.cnblogs.com/pingfan21/p/7478242.html

  • 大屏设计中echart 各种图形元素记录

     

    注:如果需要百度地图,需要百度账号生成apikey调用百度地图链接 

    下面列出的是利用echart开发数据大屏和管理驾驶舱所遇到的和值得记录下来的点。包含飞行运动轨迹,GPS百度地图和柱状图边距,文本倾斜显示,饼状图,异型图,世界地图,中国地图下钻地图,折线图,雷达图,云标签图,自动轮播效果等等

    0.Echart 数据

    X轴标题倾斜

    axisLabel:{

    Rotate:60 //倾斜角度

    }

    1、柱状体刚开始的距离

    xAxis: [{

        // boundaryGap: false,

    2、横向柱状图和纵向柱状图的区别,在于 纵向树状图

    yAxis:【type: ‘value’,】

    xAxis:【type: ‘category’,】 

    3、给X轴Y轴,加单位

    echarts柱状图的XY轴加单位的写法

    yAxis : [

            {

                type : ‘value’,

                axisLabel:{formatter:'{value} %’}

            }

    ],

    如果想控制百分比最大到100% 可添加

    yAxis : [

            {

                type : ‘value’,

                max:100,//Y轴最大值 不写的话自动调节

                axisLabel:{formatter:'{value} %’}

            }

        ],

    > max:100,//Y轴最大值 不写的话自动

    4、修改legend字体颜色

    修改legend字体颜色:

     legend: {

                    y:’55%’,

                    textStyle:{

                                fontSize: 18,//字体大小

                                color: ‘#ffffff’//字体颜色

                            },

                    data: []

                }

    修改x轴字体颜色:

    xAxis : [

              {

                      type : ‘category’,

                      data : [],

                      axisLabel: {

                                show: true,

                                textStyle: {

                                    color: ‘#ffffff’

                                }

                            }

                        }

                    ]

    修改y轴字体颜色:

    yAxis : [

                {

                       type : ‘value’,

                       name : ”,

                       axisLabel : {

                                textStyle: {

                                    color: ‘#ffffff’

                                }

                            }

                   }

            ]

    5、echart设置柱子之间的宽度,和柱子本身的宽度

            series : 

                  {

                     name:”,

                     type:’bar’,

                     barWidth:20,

                     barGap:’80%’,/*多个并排柱子设置柱子之间的间距*/

                     barCategoryGap:’50%’,/*多个并排柱子设置柱子之间的间距*/

                     data:[],

                     itemStyle: {

                         normal: {

                         barBorderRadius: false,

                             color: ‘#1E9FFF’,

                         }

                     }

                 }

    6、鼠标点击出现圆点放大

    7、柱体上有数据

    var labelOption = {

        normal: {

            show: true,

            position: ‘top’,

            align: ‘center’,

            formatter: ‘{c}’,

            fontSize: ‘100%’,

            rich: {

                // name: {

                // textBorderColor: ‘#fff’

                // }

            }

        }

    };

    orientation: portrait;/

    强制竖屏

    http://localhost:8080/cabin_portal_war_exploded/a/module/exclusive/showJspfl?dateStamp=201908&busType=%E5%85%A8%E9%99%A9%E7%B1%BB

    如何多个数据进行,ffarmat排序进行

    //数据进行push出来整个

    success: function (result) {

        $.each(result, function (index, item) {

            qddat1.push(item.channelName);

            qddat2.push(item.premiumBudget);

    // 拼接出新的数据,进行移除隐藏问题

            qddat3.push({

                “name”:item.channelName,

                “value”:item.premiumY,

                “premiumYRate”:item.premiumYRate,

                “premiumBudgetComplete”:item.premiumBudgetComplete

            });

        });

        var qddat4 = [];

        var qddat5 = [];

        var qddat6 = [], qdata7 = [], qdata8 = [];

        for (var i = qddat1.length – 1; i >= 0; i–) {

            qddat4.push(qddat1[i]);

            qddat5.push(qddat2[i]);

            qddat6.push(qddat3[i]);

           /* qdata7.push(qtbzf[i]);

            qdata8.push(qysdc[i]);*/

        }

        chart2(qddat4, qddat5, qddat6, qdata7, qdata8);

    },

    formatter: function (params) {

        var htmlStr = “”;

        for (var i = 0; i < params.length; i++) {

            if (params[i].seriesName == ‘实际’ ) {

                htmlStr += “同比增幅” + “:” + params[i].data.premiumYRate + “%” + “</br>”;

                htmlStr += “预算达成” + “:” + params[i].data.premiumBudgetComplete + “%” + “</br>”;

            }

        }

        console.log(htmlStr);

        return htmlStr;

    }

    8、设置网格背景 x轴和y轴内

    splitLine: {

    show: true,

    lineStyle: {

    color: ‘#1e2c41’, // 网格颜色

    width: 1, //网格线宽

    type: ‘solid’, //网格borderstyle

    shadowColor: ‘rgba(255, 255, 255, 0.5)’,

    shadowBlur: 10,

    shadowOffsetX:2,

    shadowOffsetY:1

    },

    },

    9.echart 设置yAxis.min y轴的数据

    min: function(value) {

    return value.min – 100;

    },

    max: function(value) {

        return parseInt(value.max +100);

    }

    10、去除指示线

    echarts中如何去除(修改)指示线

    tooltip:{

    axisPointer :{

    type: (‘line’ | ‘cross’ | ‘shadow’ | ‘none'(无)) ,

    lineStyle ->color: (填颜色值) ,

    type: (‘solid’ | ‘dotted’ | ‘dashed’, 树图还可以选:’curve’ | ‘broken’) ,

    width: (指示线宽) ,

    shadowColor : (指示线阴影颜色) ,

    shadowBlur: (大约0的数) ,

    shadowOffsetX : (横向偏移正右负左) ,

    shadowOffsetY : (纵向偏移正上负下)

    }

    }

    11、x轴y轴颜色

    xAxis: [{

    type: ‘category’,

    axisLine: { //x轴颜色

    lineStyle: {

    color: ‘#1e2c41’

    }

    },

    splitLine: { //网格颜色

    interval: 0,

    show: true,

    lineStyle: {

    color: ‘#1e2c41’,

    width: 1,

    type: ‘solid’,

    shadowColor: ‘rgba(255, 255, 255, 0.5)’,

    },

    },

    boundaryGap: 10,

    data: dataX

    // data: [‘2015’, ‘2016’, ‘2017’, ‘2018’, ‘2019’]

    }],

    12、tip总是显示

    13扩展效果

    圈层颜色修改

    color:’blue’,

    series: [{

    type: ‘effectScatter’,

    coordinateSystem: ‘geo’,

    zlevel: 2,

    rippleEffect: { //涟漪特效

    color:’white’,

    period: 4, //动画时间,值越小速度越快

    brushType: ‘stroke’, //波纹绘制方式 stroke, fill

    scale: 20, //波纹圆环最大限制,值越大波纹越大

    },

    label: {

    normal: {

    show: true,

    position: ‘right’, //显示位置

    offset: [5, 0], //偏移设置

    formatter: function(params) { //圆环显示文字

    return params.data.name;

    },

    fontSize: 13,

    },

    emphasis: {

    show: false

    }

    },

    // symbol: ‘circle’,

    showSymbol: false,

    hoverAnimation: true,

    itemStyle: {

    normal: {

    color: ‘#ec8000’, //设置图例颜色cricle边框

    borderWidth: 2,

    show: false,

    }

    },

    // symbol: ‘circle’, //折点设定为实心点

    symbolSize: function(val) {

    return 8; //圆环大小

    },

    data: res11

    },

    14、echart legend 用自定义图片

    当折线图时,legend默认时rect形式,如果需要改图例形状,可以自己设置legend的icon属性

    legend: {

        icon:’stack’

    },

    15、自定义每个图例样式:为data的每个对象修改icon属性

    legend:{

        show:true,

        orient:’horizontal’,

        borderColor:’#df3434′,

        borderWidth:2,

        data:[

            {

                name:’蒸发量’,

                textStyle:{

                    fontSize:12,

                    fontWeight:’bolder’,

                    color:’#cccccc’

                },

                icon:’stack’

            },

            {

                name:’降水量’,

                textStyle:{

                    fontSize:12,

                    fontWeight:’bolder’,

                    color:’#df3434′

                },

                icon:’pie’

            }

        ]

    }

    2、修改图例的图标为自定义图片

      首先我找了如下两张图片放在根目录下的images文件夹下

    legend:{

        show:true,

        orient:’horizontal’,

        borderColor:’#df3434′,

        borderWidth:2,

        data:[

            {

                name:’蒸发量’,

                textStyle:{

                    fontSize:12,

                    fontWeight:’bolder’,

                    color:’#cccccc’

                },

                icon:’image://./images/icon1.png’//格式为’image://+icon文件地址’,其中image::后的//不能省略

            },

            {

                name:’降水量’,

                textStyle:{

                    fontSize:12,

                    fontWeight:’bolder’,

                    icon:’image://./images/icon2.png’//格式为’image://+icon文件地址’,其中image::后的//不能省略

                },

                icon:’pie’

            }

        ]

    }

    legend:{

    itemWidth: 10 , //设置图片宽度为10

    itemHeight: 10 //设置图片高度为10

    }

    15、html页面地图图层,display:none; display:block

    type: ‘scatter’,

    coordinateSystem: ‘geo’, 出现数据被隐藏的情况。

    可以把地图的areaColor设置为有色进行检查

    itemStyle: {

    normal: {

    areaColor: ‘none’,

    borderWidth: ‘0px’,

    borderColor: ‘none’

    },

    emphasis: {

    areaColor: ‘none’

    }

    }

    数组状的字符串,转成对象数组

    eval(“(“+data[i].carLine+”)”);

    Ajax出现进入到error,解决方案是空白和json对象的属性值key值是没有双引号

    16、饼状图 指引线

        series : [

            {

                type: ‘pie’,

                radius : ‘65%’,

                center: [‘50%’, ‘50%’],

                selectedMode: ‘single’,

                data:[

                    {value:535, name: ‘荆州’},

                    {value:510, name: ‘兖州’},

                    {value:634, name: ‘益州’},

                    {value:735, name: ‘西凉’}

                ],

                itemStyle: {

                    emphasis: {

                        shadowBlur: 10,

                        shadowOffsetX: 0,

                        shadowColor: ‘rgba(0, 0, 0, 0.5)’

                    }

                },

                 label: {

                    normal: {

                        show:true,//标签隐藏

                        // position: ‘center’

                    },

                    emphasis: {

                        show: true,

                        textStyle: {

                            fontSize: ’30’,

                            fontWeight: ‘bold’

                        }

                    }

                },

                labelLine:{//指示线

                    show:true

                }

            }

        ]

    17、116.404, 39.915 百度地图设置中心点不起作用 echart

     缺少 Cannot read property ‘0’ of undefined

        at e.getLineCoords (echarts-3.8.5.min.js:22)

    地图的中心点在左上角

    只要先去show

    然后再生成

     Math.max.apply

    取出数组中最大数据

     Math.max.apply(null, [‘1′,’2′,’3.1′,’3.2’])

    < 3.2

     

    17、百度地图和echart结合,出现个个性地图设置

    地图版本要用v3.0 样式

    var bmap = myChart.getModel().getComponent(‘bmap’).getBMap();

    bmap.setMapStyleV2({

    styleId: ‘7479f0ec695598ad21b6ddfb3367d34f’

    });

    map.setViewport(pointsView)

    var points = [point1, point2,point3];

    var view = map.getViewport(eval(points));

    var mapZoom = view.zoom; 

    var centerPoint = view.center; 

    map.centerAndZoom(centerPoint,mapZoom);

    //异型图的加载,和边距。边距barCategoryGap和barWidth不能同时设置,且x轴的和数据个数要一致

    option = {

        xAxis: {

            data: [‘a’, ‘b’, ‘c’, ‘d’,’3′,’3′,’3′,’9′,’9′],

            axisTick: {show: false},

            axisLabel: {

                formatter: ‘barGap: \’-100%\”

            }

        },

        yAxis: {

            splitLine: {show: false}

        },

        animationDurationUpdate: 1200,

        series: [{

            type: ‘bar’,

            itemStyle: {

                normal: {

                    color: ‘#ddd’

                }

            },

            silent: true,

            // barWidth: 40,

            barGap: ‘-100%’, // Make series be overlap

            data: [60, 60, 60, 60, 60, 60, 60, 60],

            barCategoryGap:’20%’

        }, {

            type: ‘bar’,

            // barWidth: 40,

            z: 10,

            data: [45, 60, 13, 25, 60, 60, 60, 60],

            barCategoryGap:’20%’

        }]

    };

    var barGaps = [‘30%’, ‘-100%’];

    var loopIndex = 0;

    // setInterval(function () {

    //     var barGap = barGaps[loopIndex];

    //     myChart.setOption({

    //         xAxis: {

    //             axisLabel: {

    //                 formatter: ‘barGap: \” + barGap + ‘\”

    //             }

    //         },

    //         series: [{

    //             barGap: barGap

    //         }]

    //     });

    //     loopIndex = (loopIndex + 1) % barGaps.length;

    // }, 2000);

    18、多个设置轮播图 后台控制tooltip的时候会出现,多个tooltip直接删除div即可(利用打印来调试程序)

    19.echart运动线轨迹飞行图 3.2.2版本以上

    function convertDataLines(data) {

    var res = [];

    var toCoord = [‘111.461338’, ‘40.752298’];

    for (var i = 0; i < data.length; i++) {

    var dataItem = data[i];

    res.push(

    {

    coords: [

        dataItem.value,  // 起点

        toCoord   // 终点

    ]

    }

    );

    }

    return res;

    };

  • https页面引用外部http文件出现“Mixed Content”

    Mixed Content: The page at ‘https://www.XXXX.com/’ was loaded over HTTPS, but requested an insecure script ‘http://libs.baidu.com/jquery/1.4.2/jquery.min.js’. This request has been blocked; the content must be served over HTTPS.

    刚刚在看小说的时候,发现某小说网站控制台报了俩错误,查看了一下发现是因为,https安全机制页面,引入了baidu的jQuery的文件使用的是http导致的。
    http:超文本传输协议
    https:添加了加密及认证机制的http成为https,https要比http慢2-100倍

    解决方式:

    1、可以把外部资源下载到自己服务器上,统一使用https(如果使用的是外部分享邮箱之类的,这种能方法不可取)
    2、可以在页面头部加上

    会把http请求转化为https请求

    扩展

    Content-Security-Policy(CSP 内容安全政策)



    default-src 'self'; img-src https://*; child-src 'none';

    • 作用
    1. 使用白名单的方式告诉客户端(浏览器)允许加载和不允许加载的资源。
    2. 内容安全策略   (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段

    content 内部代码

    upgrade-insecure-requests: 指示 User Agent 将 HTTP 更改为 HTTPS,重写网址架构。 该指令适用于具有大量旧网址(需要重写)的网站。
    base-uri: 用于限制可在页面的 <base> 元素中显示的网址。
    child-src: 用于列出适用于工作线程和嵌入的帧内容的网址。例如:child-src https://youtube.com 将启用来自 YouTube(而非其他来源)的嵌入视频。 使用此指令替代已弃用的 frame-src 指令。
    connect-src: 用于限制可(通过 XHR、WebSockets 和 EventSource)连接的来源。
    font-src: 用于指定可提供网页字体的来源。Google 的网页字体可通过 font-src https://themes.googleusercontent.com 启用。
    form-action: 用于列出可从 <form> 标记提交的有效端点。
    frame-ancestors: 用于指定可嵌入当前页面的来源。此指令适用于 <frame>、<iframe>、<embed> 和 <applet> 标记。此指令不能在 <meta> 标记中使用,并仅适用于非 HTML 资源。
    frame-src: 已弃用。请改用 child-src。
    img-src: 用于定义可从中加载图像的来源。
    media-src: 用于限制允许传输视频和音频的来源。
    object-src: 可对 Flash 和其他插件进行控制。
    plugin-types: 用于限制页面可以调用的插件种类。
    report-uri: 用于指定在违反内容安全政策时浏览器向其发送报告的网址。此指令不能用于 <meta> 标记
    style-src: 是 script-src 版的样式表

    参考文档:
    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP

  • js函数带括号和不带括号的区别

    先说结果

    1、加了括号的代表执行完毕得到函数的结果(括号的二义性,是“函数的调用运算符”)

    2、没加括号的,查看该函数的完整信息。指向函数的指针,只是传递了函数题所在的地址位置。

    举例:

    //demo1
    function demo1() {
        var m = 3;
        alert(m);
    }
    function demo2() {
        var m = 55;
        alert(m);
    }
    
    var e = document.getElementById('btn'); 
       
    // 点击的时候才进行执行  点击按钮“btn”后弹出3
    e.addEventListener('click', demo1); 
        
    // 直接就已经弹出进行了执行 弹出55    
    e.addEventListener('click', demo2());
    
    //demo2
    function foo(){
     var m = 3;
    return m;
    }
    var a = foo;
    var b = foo();
    console.log(a); //函数体
    console.log(b);//3

    其中括号的二义性。感觉像通假字,可以有俩意思。比如一个用红色墨水写的“蓝”字。这个字是什么颜色?蓝?红?

    2.7.2 括号"( )"的二义性
    
    我们来看下面语句中的括号"( )"应该是什么含义呢?
    
    var str = typeof(123);  
    var str = ('please input a string', 1000); 
    第一个 typeof 看起来好像被当成了函数使用--这是否说明 typeof 为一个"内部函数"呢?而第二行代码,你相信它会成功执行并使 str"意外地"赋值为 1000 吗?括号首先可以作为语句中的词法元素。例如函数声明中的"虚拟参数表":
    //声明函数时,括号用做参数表  
    function foo(v1, v2) {  
    //…  
    } 
    第二种情况,就是括号只作为"传值参数表(这有别于函数声明中的'虚拟参数表')",注意这里它并不表达函数调用的含义。目前为止,它只出现在 new 关键字的使用中:new关键字用于创建一个对象实例并负责调用该构造器函数,如果存在一对括号"( )"指示的参数表,则在调用构造器函数时传入该参数表,对此的具体分析,我们已经在"2.5.1.1使用构造器创建对象实例"中讲述过了。例如:
    //构造对象时,用于传入初始化参数  
    var myArray = new Array('abc', 1, true); 
    接下来,它也可以在 with、for、if、while 和 do...while 等语句,以及 catch()等子句中用来作为限定表达式的词法元素:
    // for语句(for…in语句类同)  
    for ( initialize; test; increment )  
    statement  
     
    // if语句  
    if ( expression )  
    statement  
     
    // while语句  
    while ( expression )  
    statement  
     
    // do…while语句  
    do  
    statement  
    while ( expression ) 
    在充当 if、while 和 do...while 语句中的词法元素时,括号会有"将表达式结果转换为布尔值"的副作用(参见"5.7.3.2语句(语义)导致的类型转换")。在很多时候,语句中的括号会产生类似于"运算"这样的附加效果。
    
    第四种情况,是括号"( )"用于强制表达式运算。这种情况下,基本含义是我们通常说的强制运算优先级。但事实上,不管有没有优先级的问题,括号总是会强制其内部的代码作为表达式运算。例如我们在这一小节开始列举的例子:
    
    var str1 = typeof(123);  
    var str2 = ('please input a string', 1000); 
    在第 1 行代码中,"( )"强制 123 作为单值表达式运算,当然运算结果还是 123,于是再进行 typeof 运算。所以这里的一对括号起到了强制运算的作用。同样的道理,第 2 行代码里的一对括号也起到相同的作用,它强制两个单值表达式做连续运算,由于连续运算符","的返回值是最后一个表达式的值,因此这个结果返回了 1000。所以我们要意识到,上面的第 1 行代码并没有调用函数的意思,而第 2 行代码将使 str2 被赋值为 1000。
    
    最后一种情况最为常见:作为函数/方法调用运算符。例如:
    
    //有(),表明函数调用  
    foo();  
    //没有(),则该语句只是一个变量的返回。  
    foo; 
    我们一再强调:函数调用过程中的括号"( )"是运算符。也因此得出推论,当"( )"作为运算符时,它只作用于表达式运算,而不可能作用于语句。所以你只能将位于:
    function foo() {  
    return( 1 + 2);  
    } 
    这个函数内的、return 之后的括号理解成"强制表达式优先级",而不是理解成"把 return当成函数或运算符使用"。所以从代码格式化的角度上来说,在下面两种书写方法中,第二种才是正确的:
    
    //第一种,像函数调用一样,return后无空格  
    return(1 + 2);  
     
    //第二种,return后置一空格  
    return (1 + 2); 
    基于同样的理由,无论"break (my_label)"看起来如何合理,也会被引擎识别为语法错误。因为 my_label 只是一个标签,而不是可以交给"( )"运算符处理的运算元,标签与运算元属于两个各自独立的、可重复(而不发生覆盖)的标识符系统。
  • vue的MVVM模型

    1、mvvm简介:
    mvvm是model-view-viewModel的缩写,是一种基于前端开发的架构模式,其核心是提供对view和viewModel的双向数据绑定,这使得viewModel的状态改变可以自动传递给view,即所谓的数据双向绑定。
    vue.js是一个提供了mvvm风格的双向数据绑定的js库,专注于view层。它的核心是mvvm中的vm。viewModel负责连接view和model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效和便捷。

    2、为什么会出现MVVM
    以前我只知道mvc,也是在大学学java的时候接触到的。ssh框架就是用来构建一个标准的mvc框架。说实话mvc,始终没有深刻理解。
    只知道model view control,可见是MVC满足不了前端开发了。找到了以下的理解。

    标记语言和MVVM

    随着20世纪初web的崛起,HTML跟JS这样标记语言+程序语言的组合模式开始变得令人注目。逐渐推出的Flex、Sliverlight、QT、WPF、JSF、Cocoa等UI系统不约而同地选择了标记语言来描述界面。

    在这样的架构中,view(或者说叫控件,不但是从依赖关系上跟程序的其他部件解耦,而且从语言上跟其它部分隔离开来。

    标记语言的好处是,它可以由非专业的程序员产生,通过工具或者经过简单培训,一些设计师可以直接产生用标记语言描述的UI。想要突破这个限制使得view跟其它部分异常耦合可能性也更低。

    然而这样的系统架构中,MVC和MVP模式已经不能很好地适用了。微软架构师John Gossman在WPF的XAML模式推出的同时,提出了MVVM的概念。

    WPF得MVVM正式说明了它的view的概念跟MVC中的view的概念的区别。这里简单画了一下:

    image

    在MVVM模式中,数据绑定是最重要的概念,在MVC和MVP中的view和model的互相通讯,被以双向绑定的方式替代,这进一步把逻辑代码变成了声明模式。

    1、数据对象(Model),与dom绑定的数据
    2、视图对象(View),里面封装了对dom节点的解析、事件绑定、视图更新渲染等方法
    3、视图模板绑定对象(ViewModel),这也是mvvm实现的核心方法,通过defineProperty将Model对象中的数据复制到了View对象中,并对数据进行了监控,每当get或set时都会触发自定义事件,完成对视图的更新。

    详细代码实例
    https://segmentfault.com/a/1190000014739158






    以下文章转载自winter-cn
    https://www.cnblogs.com/winter-cn/p/4285171.html

    谈谈UI架构设计的演化

    经典MVC

    在1979年,经典MVC模式被提出。

    在当时,人们一直试图将纯粹描述思维中的对象与跟计算机环境打交道的代码隔离开来,而Trygve Reenskaug在跟一些人的讨论中,逐渐剥离出一系列的概念,最初是Thing、Model、View、Editor。后来经过讨论定为Model、View和Controller。作者自言“最难搞的就是给这些架构组件起名字”。

    因为当时的软件环境跟现在有很大不同,所以经典MVC中的概念很难被现在的工程师理解。比如经典MVC中说:“view永远不应该知道用户输入,比如鼠标操作和按键。”对一个现代的软件工程师来说,这听上去相当不可思议:难道监听事件不需要类似这样的代码吗?

    view.onclick = ......
    

    但是想想在70年代末,80年代初,我们并没有操作系统和消息循环,甚至鼠标的光标都需要我们的UI系统来自行绘制,所以我们面对的应该是类似下面的局面:

    mouse.onclick = ......
    mouse.onmove = ......
    

    当鼠标点击事件发生后,我们需要通过view的信息将点击事件派发到正确的view来处理。假如我们面对的是鼠标、键盘驱动这样的底层环境,我们就需要一定的机制和系统来统一处理用户输入并且分配给正确的view或者model来处理。这样也就不难理解为什么经典MVC中称”controller是用户和系统之间的链接”。

    因为现在的多数环境和UI系统设计思路已经跟1979年完全不同,所以现代一些喜好生搬硬套的”MVC”实现者常常会认为controller的输入来自view,以至于画出model、view、controller之间很奇葩的依赖关系:

    image

    我们来看看Trygve Reenskaug自己画的图(这恶趣味的骷髅啊……):

    image

    值得一提的是,其实MVC的论文中,还提到了”editor”这个概念。因为没有出现在标题中,所以editor声名不著。MVC论文中推荐controller想要根据输入修改view时,从view中获取一个叫做editor的临时对象,它也是一种特殊的controller,它会完成对view和view相关的model的修改操作。

    控件系统

    MVC是一种非常有价值的架构思路,然而时代在变迁,随着以windows系为代表的WIMP(window、icon、menu、pointer)风格的应用逐渐成为主流,人们发现,view和controller某些部件之间的局部性实际上强于controller内部的局部性。于是一种叫做控件(control)的预制组件开始出现了。

    控件本身带有一定的交互功能,从MVC的视角来看,它既包含view,又包含controller,并且它通过”属性”,来把用户输入暴露给model。

    controller的输入分配功能,则被操作系统提供的各种机制取代:

    • 指针系统:少数DOS时代过来的程序员应该记得,20年前的程序中的“鼠标箭头”实际上是由各个应用自己绘制的,以MVC的视角来看,这应当属于一个”PointerView”的职责范畴。但是20世纪以后,这样的工作基本由操作系统的底层UI系统来实现了。
    • 文本系统:今天我们几乎不需要再去关心文本编辑、选中、拖拽等逻辑,对web程序员可以尝试自己用canvas写一个文本编辑框来体验一下上个时代程序员编写程序的感受。你会发现,选中、插入/覆盖模式切换、换行、退格、双击、拖拽等逻辑异常复杂,经典MVC模式中通常使用TextView和TextEditor配合来完成这样的工作,但是今天几乎找不到需要我们自己处理这些逻辑的场景。
    • 焦点系统:焦点系统通过响应鼠标、tab键等消息来使得控件获得操作系统级唯一的焦点状态,所有的键盘事件通常仅仅会由拥有焦点的控件来响应。在没有焦点系统的时代,操作系统通常是单任务的,但是即使是单一应用,仍然要自己管理多个controller之间的优先权和覆盖逻辑,焦点系统不但从技术上,也从交互设计的角度规范化了UI的输入响应,而最妙的是,焦点系统是对视觉障碍人士友好的,现在颇多盲人用读屏软件都是强依赖焦点系统的。

    所以时至今日,MVC,尤其是其中controller的功能已经意义不大,若是在控件系统中,再令所有用户输入流经一个controller则可谓不伦不类、本末倒置。MVVM的提出者,微软架构师John Gossman曾言:“我倾向于认为它(指controller)只是隐藏到后台了,它仍然存在,但是我们不需要像是1979年那样考虑那么多事情了”

    MVP

    1996年,Taligent公司的CTO,Mike Potel在一篇论文中提出Model-View-Presenter的概念。

    在这个时期,主流的view的概念跟经典MVC中的那个“永远不应该知道用户输入”的view有了很大的差别,它通常指本文中所述的控件,此时在Mike眼中,输入已经是由view获得的了:

    image

    Model-View-Presenter是在MVC的基础上,进一步规定了Controller中的一些概念而成的:

    image

    对,所以,不论你按照Mike还是Trygve的理解方式,MVP和MVC的依赖关系图应该是一!模!一!样!的!因为Mike的论文里说了“we refer to this kind(指应用程序全局且使用interactor, command以及selection概念的) of controller as a presenter”。presenter它就是一种controller啊!

    image

    把依赖关系画成这样也是醉了啊!不管你信不信我反正是不信啊!

    标记语言和MVVM

    随着20世纪初web的崛起,HTML跟JS这样标记语言+程序语言的组合模式开始变得令人注目。逐渐推出的Flex、Sliverlight、QT、WPF、JSF、Cocoa等UI系统不约而同地选择了标记语言来描述界面。

    在这样的架构中,view(或者说叫控件,不但是从依赖关系上跟程序的其他部件解耦,而且从语言上跟其它部分隔离开来。

    标记语言的好处是,它可以由非专业的程序员产生,通过工具或者经过简单培训,一些设计师可以直接产生用标记语言描述的UI。想要突破这个限制使得view跟其它部分异常耦合可能性也更低。

    然而这样的系统架构中,MVC和MVP模式已经不能很好地适用了。微软架构师John Gossman在WPF的XAML模式推出的同时,提出了MVVM的概念。

    WPF得MVVM正式说明了它的view的概念跟MVC中的view的概念的区别。这里简单画了一下:

    image

    在MVVM模式中,数据绑定是最重要的概念,在MVC和MVP中的view和model的互相通讯,被以双向绑定的方式替代,这进一步把逻辑代码变成了声明模式。

    结语

    从经典MVC到MVVM,UI架构经过数次重大变迁,一些概念也在不断变化,架构和底层环境互相影响、适配,我认为时至今日,经典MVC已经不再是UI架构的正常选项。

    更糟糕的是,今天无数经过演绎的MVC实现(如backbone)和科普文,要么是原本作者概念已经很混乱,掺杂私货,要么为了适配现代的标记语言和控件模式,自己修改了经典MVC中的一些概念和耦合关系。实际上今天MVC已经没法作为一种交流的标准词汇了。

    写此文,希望大家能了解些历史上的发展历程,莫被不严谨的文章误导。其实本文的相当多观点也是经过演绎的,所以我附上所有原始文献链接,希望大家看了以后能有自己的判断:)也欢迎大家据此指出我理解的错误之处。

  • 浏览器内核

    看到一个面试谈到兼容,想到浏览器内核,浏览器大战引发的兼容性,
    浏览器厂商不同,内核不同。
    所谓的“浏览器内核”无非指的是一个浏览器最核心的部分——“Rendering Engine”,直译这个词汇叫做“渲染引擎”,不过我们也常称其为“排版引擎”、“解释引擎”。这个引擎的作用是帮助浏览器来渲染网页的内容,将页面内容和排版代码转换为用户所见的视图。

    注:有时候我们所说的“浏览器内核”甚至“渲染引擎”,其实除了渲染引擎,也悄悄包含了javascript引擎,如WebKit,它由渲染引擎WebCore和javascript引擎JSCore组成。

    常见的浏览器内核(或者说渲染引擎)有很多个,如Trident、Gecko、WebKit等等,不同的内核对网页编写语法的解释也有不同,进而导致同一个页面在不同内核的浏览器下显示出来的效果也会有所出入,这也是前端工程师需要让作品兼容各种浏览器的原因。

    我们常常喜欢把浏览器内核与某浏览器名称直接挂钩起来,如IE内核、Chrome内核,其实是不全面的说法。比如Opera在7.0版本到12.16版本中采用的是独立研发的Presto引擎,但在后续跟随了Chrome的脚步加入了WebKit大本营,放弃了Presto;另外即使名称相同,但版本不同的引擎也可能存在较大差别。比如IE6使用的是Trident早期版本,存在许多bug,性能也较低。而最新的IE11所使用的Trident7.0版本已经可以支持WebGL(3D绘图标准)以及HTML5大部分标准。

    下面按照各个主流浏览器,介绍下它们所使用的浏览器内核的历程。

    Internet Explorer:
    IE开发计划开始于1994年夏天,微软为抵抗当时主流的网景Netscape Navigator,要在Windows中开发适合自己的浏览器,但微软并没有时间从零开始。因此和Spyglass合作,于是IE从早期一款商业性的专利网页浏览器Spyglass Mosaic派生出来,虽然Spyglass Mosaic与NCSA Mosaic(首款应用得最广泛的网页浏览器)甚为相似,但Spyglass Mosaic则相对地较不出名并使用了NCSA Mosaic少量的源代码。

    1996年,微软通过给予季度费用和部分收入从Spyglass中取得了Spyglass Mosaic的源代码和授权。从而使IE逐渐成为微软专属软件。它采用的排版引擎(俗称内核)为Trident。每一次新的IE版本发布,也标志着Trident内核版本号的提升。

    下面是各Trident版本信息:

    冷知识:除Trident之外,微软还有另一个网页浏览器排版引擎,称为Tasman,它是使用在「Internet Explorer for Mac」的排版引擎。相较于Trident,Tasman引擎对网页标准有较佳的支持,但微软自04年开始已经停止了Mac计算机版本的 Internet Explorer的开发。

    Safari
    Safari是苹果公司开发的浏览器,使用了KDE(Linux桌面系统)的KHTML作为浏览器的运算核心,Safari所用浏览器内核的名称是大名鼎鼎的WebKit。 Safari在2003年1月7日首度发行测试版,并成为Mac OS X v10.3与之后版本的默认浏览器,也成为苹果其它系列产品的指定浏览器(也已支持Windows平台)。

    如上述可知,WebKit前身是KDE小组的KHTML引擎,可以说WebKit是KHTML的一个开源的分支。当年苹果在比较了Gecko和KHTML后,选择了后者来做引擎开发,是因为KHTML拥有清晰的源码结构和极快的渲染速度。

    需要了解的是,虽然我们称WebKit为浏览器内核(或浏览器引擎),但不太适合直接称之为我们开头提到的Rendering Engine(渲染引擎),因为WebKit本身主要是由两个引擎构成的,一个正是渲染引擎“WebCore”,另一个则是javascript解释引擎“JSCore”,它们均是从KDE的渲染引擎KHTML及javascript解释引擎KJS衍生而来。

    在2010年4月,苹果公司宣布了其浏览器引擎Webkit的最新项目 Webkit2。Webkit2的目标是实现独立进程与非阻断式API。

    WebKit可以说是苹果公司给开源世界的一大贡献,基于此开源引擎,衍生了多个WebKit分支,如下面要介绍的Chrome的浏览器引擎。

    Chrome / Chromium
    谷歌Chrome/Chromium浏览器从08年创始至今一直使用苹果公司的WebKit作为浏览器内核原型,是WebKit的一个分支,我们可以称之为Chromium引擎(注意我们这里说的是Chromium引擎,而不是Chromium浏览器)。

    这里顺便介绍下Chrome和Chromium两个浏览器的区别——Chromium浏览器是谷歌为发展自家的浏览器Chrome而开启的计划,所以Chromium相当于Chrome的工程版或称实验版(尽管Chrome自身也有β版阶段),新功能会率先在Chromium上实现,待验证后才会应用在Chrome上。Chromium一天最多可以更新十几二十个版本,实验性的新特性都会现在这里放出,但是Chromium本身其实并不稳定;而Chrome总共有四个更新分支:Canary、Dev、Beta、Stable,稳定性依次增强。

    我们说回引擎。Chromium引擎虽然是属于WebKit的分支,却把WebKit的代码梳理得可读性提高很多,所以以前可能需要一天进行编译的代码,现在只要两个小时就能搞定。因此Chromium引擎和其它基于WebKit的引擎所渲染页面的效果也是有出入的。基于以上原因,有的地方会把Chromium引擎跟WebKit区分开来,有的地方则直接把Chromium引擎归为WebKit(比如维基百科),其实都有其道理。

    然而在13年发布的Chrome 28.0.1469.0版本开始,Chrome放弃Chromium引擎转而使用最新的Blink引擎(基于WebKit2——苹果公司于2010年推出的新的WebKit引擎),Blink对比上一代的引擎精简了代码、改善了DOM框架,也提升了安全性。

    Opera
    Opera浏览器,是一款挪威Opera Software ASA公司制作的支持多页面标签式浏览的网络浏览器。是跨平台浏览器可以在Windows、Mac和Linux三个操作系统平台上运行。Opera浏览器创始于1995年4月,到2014年3月4日,官方发布的个人电脑用的最新版本为Opera20。

    Opera的一个里程碑作品是Opera7.0,因为它使用了Opera Software自主开发的Presto渲染引擎,取代了旧版Opera 4至6版本使用的Elektra排版引擎。

    Presto加入了动态功能,例如网页或其部分可随着DOM及Script语法的事件而重新排版。Presto在推出后不断有更新版本推出,使不少错误得以修正,以及阅读Javascript效能得以最佳化,并成为当时速度最快的引擎。

    然而为了减少研发成本,Opera在2013年2月宣布放弃Presto,转而跟随Chrome使用WebKit分支的Chromium引擎作为自家浏览器核心引擎。

    在Chrome与2013年推出Blink引擎(也是基于WebKit的分支)之后,Opera也紧跟其脚步表示将转而使用Blink作为浏览器核心引擎。

    Firefox
    Mozilla Firefox是一个开源网页浏览器,原名是Firebird,2004年2月9日,Mozilla Firebird决定改称Mozilla Firefox。Firefox浏览器使用的是Gecko内核,其发展历程如下:

    1997年,网景收购了DigitalStyle。当时,网景浏览器在各方面的表现已经比不上她的主要竞争对手Internet Explorer。网景开始研发下一代的排版引擎,并期望把新的排版引擎应用于下一版本的网景浏览器上。

    1998年初,Mozilla计划开始执行。这个新的排版引擎名为Raptor,以开发源码的方式发放于互联网上。后来,因为商标问题,Raptor改名为NGLayout(即next generation layout之意)。而最后NGLayout就被网景重新命名为Gecko。

    2003年7月15日时代华纳解散了网景公司,大部分开发者被解雇。Mozilla基金会亦在当天成立,继续推动着Gecko的发展。时至今天,Gecko仍继续由Mozilla的雇员和义工所维护和发展。

    最后还是再谈谈javascript引擎(后面统称JS引擎)这东西。我们上述的渲染引擎主要是负责HTML、CSS以及其他一些东西的渲染,而JS引擎则主要负责对javascript的渲染,一个JS引擎的好坏决定了一个浏览器对脚本的加载和执行速度,也影响了其跑分。

    下方列出各种主流浏览器各自的JS引擎,了解下即可:

    Firefox:
    SpiderMonkey:第一款JavaScript引擎,由Brendan Eich在Netscape Communications时编写,用于Mozilla Firefox 1.0~3.0版本。

    Rhino:由Mozilla基金会管理,开放源代码,完全以Java编写。

    TraceMonkey:基于实时编译的引擎,其中部份代码取自Tamarin引擎,用于Mozilla Firefox 3.5~3.6版本。

    JaegerMonkey:德文Jäger原意为猎人,结合追踪和组合码技术大幅提高性能,部分技术借凿了V8、JavaScriptCore、WebKit:用于Mozilla Firefox 4.0以上版本。

    IonMonkey:可以对JavaScript编译后的结果进行优化,用于Mozilla Firefox 18.0以上版本。

    OdinMonkey:可以对asm.js进行优化,用于Mozilla Firefox 22.0以上版本。

    Chrome:
    V8:开源,由Google丹麦开发,是Google Chrome的一部分。

    注:我们上面提到Chrome是基于WebKit的分支,而WebKit又由渲染引擎“WebCore”和JS解释引擎“JSCore”组成,可能会让你搞不清V8和JSCore的关系。你可以这样理解——WebKit是一块主板,JSCore是一块可拆卸的内存条,谷歌实际上认为Webkit中的JSCore不够好,才自己搞了一个V8 JS引擎,这就是Chrome比Safari在某些JS测试中效率更高的原因。

    IE:
    Chakra:中文译名为查克拉,用于Internet Explorer 9的32位版本及IE10+。

    Opera:
    Linear A:用于Opera 4.0~6.1版本。

    Linear B:用于Opera 7.0~9.2版本。

    Futhark:用于Opera 9.5~10.2版本。

    Carakan:由Opera软件公司编写,自Opera10.50版本开始使用。

    其它:
    KJS:KDE的ECMAScript/JavaScript引擎,最初由Harri Porten开发,用于KDE项目的Konqueror网页浏览器中。

    Narcissus:开放源代码,由Brendan Eich编写(他也参与编写了第一个SpiderMonkey)。

    Tamarin:由Adobe Labs编写,Flash Player 9所使用的引擎。

    Nitro(原名SquirrelFish):为Safari 4编写。

  • vue了解

    1、对于MVVM的理解

    MVVM是Model View iewModel的缩写。

    Model代表数据模型,也可以在model中定义数据修改和操作的业务逻辑。

    view代表视图UI组件,它负责将数据模型转化为视图展现出来

    viewModel监听模型数据的改变和控制视图行为、处理用户交互。连接view和model的,同步之间的对象,建立连接。

    在MVVM架构下,view和model之间并没有直接的联系,而是通过viewModel进行交互,model和viewModel之间的交互式双向的,因此view数据变化会同步到model中,二model数据的变化也会立即反映到view上。

    viewModel通过双向数据绑定把view层和model层连接了起来,而view和model之间的同步工作完全是自动的,无需人为干涉,因此开发者只需要关注业务逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题,复杂的数据状态维护完全由MVVM来统一管理。

    2、VUE的生命周期

    beforeCreate(创建前) 在数据观测和初始化事件还未开始
    created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来
    beforeMount(载入前)在挂在开始之前被调用,线管的render函数首次被调用。实例已完成以下的配置:编译模板,把data的数据和模板生成HTML。注意此时还没有挂载HTML在页面上
    mounted(载入后)在el被创建的vm.$el替换,并挂载到实力上去后调用。实例已完成以下的配置:用上面编译好的html渲染到html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax的交互。
    beforeUpdate(更新前)在数据更显之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
    update(更新后)在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务端渲染期间不被调用。
    beforeDestory(销毁前)在实例销毁之前调用。实例仍然完全可用。
    destroyed(销毁后)在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器渲染期间不被调用。

    ①什么是vue生命周期?
    答:vue实例从创建到销毁的过程就是生命周期。从开始创建、初始化数据、编译模板、挂载(DOM)→渲染更新→渲染销毁等一系列过程,称之为VUE的生命周期。

    ②vue的生命周期的作用是什么?
    答:它的生命周期有多个事件钩子,让我们在控制整个VUE实例的过程时更容易形成好的逻辑。

    ③vue的生命周期总共有几个阶段?
    答:它可以总共分为8个阶段:创建前/后 载入前/后  更新前/后,销毁前/后

    ④第一次页面加载会触发那几个钩子
    答:会触发下面几个钩子 beforeCreate created beforeMount mounted

    ⑤DOM渲染在哪个周期中已经完成?
    答:DOM渲染在mounted中已经完成

    3、VUE实现数据双向绑定的原理 object.definePropty()
    UVE实现数据双向绑定主要是:采用数据劫持接口发布者订阅模式的方式,通过object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。档把一个普通的javascript对象传给vue实例来作为她的data选项时,vue将便利它的属性,用Obeject.defineProperty将他们转为getter/setter。用户看不到getter/setter,但是在内部它们让vue追踪依赖,在属性被访问和修改时通知变化。

    vue的数据双向绑定将MVVM作为数据绑定的入口,整合observer,compile和watcher三者,通过observer来监听自己的model的数据变化,通过compile来解析编译模板指令(vue中是用来解析{{}}),最终利用watcher搭起observe和compile之间的通信桥梁,达到数据变化 →视图更新;视图交互变化(input)→数据model变更双向绑定效果。

    4、VUE组件间的参数传值

    ①父组件和子组件传值
    父组件传给子组件:子组件通过props方法接受数据;
    子组件传给父组件:$emit方法传递参数
    ②非父子组件间的数据传递,兄弟组件传值
    eventBus,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接受事件。项目比较小时,用这个比较合适。(vuex也可以)

    5、VUE的路由实现:hash模式和history模式
    hash模式:在浏览器符号有“#”以及“#”后面的字符称之为hash,用window.location.hash读取;
    特点:hash虽然在URL中,但不包括在HTTP请求中;用来指导浏览器动作,对于服务端安全无用,hash不会重载页面。
    hash模式下,仅hash符号之间的内容会被包含在请求中,如http:xxxx.com,因此对于后端来说,及时没有做对到对路由的全覆盖,也不会返回404

    history模式history模式采用h5习特性,使用俩新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
    history模式下,前端的url必须和实际想后端发起请求的url一致,如http://wwww.xxx.com/list/id。后端如果缺少了对/list/id的路由处理,将会返回404。vue-router官网描述:不过这种模式要玩好,所以还要后台配置支持。。。所以呢,你要在服务端增加一个覆盖所有情况的候选志愿:如果url匹配不到任何静态资源,则应该返回同一个index.html页面,这个页面就是你app依赖的页面。

    6、vue与angular以及react的区别
    api vue全面

    7、vue的路由钩子函数
    首页可以控制导航跳转,beforeEach afterEach等,一般用于页面title修改,一些需要登录才能调整页面的重定向登录
    beforeEach 有 to from next 三个
    to:route即将进入的目标路由对象
    from:route当前导航正要离开的路由
    next:function一定要调用该方法的resolve这个钩子,执行效果依赖next()方法的调用参数。可以控制页面的跳转。

    8、VUEX是什么?怎么使用?哪种功能场景使用它?
    只用来读取的状态集中放在store中;改变状态的方式是提交mutations,这个是同步的数据,异步逻辑应该封装在acticon里面。
    在main.js引入store,注入,建一个目录store . export
    场景:单页面应用中,组件之间的状态,登录状态等




    state
    vuex使用单一状态树,即每个应用将仅仅包含一个stroe实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
    mutations
    mutations定义的方法动态修改vuex的store的状态或数据。
    getters
    类似vue计算属性,主要通过过滤一些数据
    action
    actions可以理解为通过将mutations里面处理数据的方法变成可以异步处理数据的方法,简单说就是异步操作数据。view层通过store.dispath来分发action

    const store=new Vuex.Store({
    state:{
    count:0
    },
    mutations:{
    increment(state){
    state.count++
    }
    },
    actions:{
    increment(context){
    context.commit(‘increment’)}
    }
    })

    modules
    项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters使得结构非常清晰,方便管理

    const moduleA = {
    state: { … },
    mutations: { … },
    actions: { … },
    getters: { … }
    }
    const moduleB = {
    state: { … },
    mutations: { … },
    actions: { … }
    }

    const store = new Vuex.Store({
    modules: {
    a: moduleA,
    b: moduleB
    })

    9、vue-cli如何新增自定义指令?
    ①创建局部指令
    var app = new Vue({
    el:’#app’,
    data:{

    },

    // 创建指令(可以多个)
    directives: {
    // 指令名称
    dir1: {
    inserted(el) {
    // 指令中第一个参数是当前使用指令的DOM
    console.log(el);
    console.log(arguments);
    // 对DOM进行操作
    el.style.width = ‘200px’;
    el.style.height = ‘200px’;
    el.style.background = ‘#000’;
    }
    }
    }



    })

    ②全局指令
    Vue.directive(‘dir2’,{
    inserted(el){

    }
    })

    ③指令的使用

    <div id="app">
        <div v-dir1></div>
        <div v-dir2></div>
    </div>
    10、vue如何自定义一个过滤器
    {{msg| capitalize }}
    var vm=new Vue({
        el:"#app",
        data:{
            msg:''
        },
        filters: {
          capitalize: function (value) {
            if (!value) return ''
            value = value.toString()
            return value.charAt(0).toUpperCase() + value.slice(1)
          }
        }
    
    全局定义过滤器
    Vue.filter('capitalize', function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    })
    
    过滤器接收表达式的值(msg)作为第一个参数。capitalize过滤器将会受到msg的值作为第一个参数

    11、对keep-alive的了解?
    keep-alive是vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。include(包含组件的缓存) exclude(排除组件的不缓存,优先级大于include)

    使用方法:
    <keep-alive include=”include_componens” exclude=”exclude_components”>
    <component>
    <!– 该组件是否缓存取决于include和exclude属性 –>
    </component>
    参数解释
    include-字符串或正则表达式,只有名称匹配的组件会被缓存
    exclude-字符串或正则表达式,任何名称匹配的组件都不会被缓存
    include和exclude的属性允许组件有条件滴缓存。二斗都可以用”,“”分隔字符串、正则表达式、数组。当使用正则或者数组的时候,要用v-bind“
    使用实例
    <keep-alive include=”a,b”>
    <component></component>
    </keep-alive>

    <!– 正则表达式(需要使用v-bind,符合匹配规则的都会被缓存) –>
    <keep-alive :include=”/a|b/”>
    <component></component>
    </keep-alive>

    <!– Array需要使用v-bind,被包含的都会被缓存 –>
    <keep-alive :include=”[‘a’,’b’]”>
    <component></component>
    </keep-alive>
    12、其他面试题
    ①css只在当前组件内起作用
    在style标签中写入scoped即可 例如<style scoped></style>


    ②v-if和v-show的区别
    v-if是按照条件渲染的,v-show是display的block和none。v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件不太可能改变,则使用 v-if 较好

    ③$route和$router的区别
    $route是”路由信息对象“,包括path,param,hash,query,fullpath,matched,name等路由信息参数。而$router是”路由实例“对象包括了路由的跳转方法,钩子函数等。

    ④vue.js的两个核心是数据驱动和组件系统

    ⑤vue的常用指令 v-for v-if v-show v-else v-bind v-on

    ⑥vue常用的修饰符 .prevent:提交页面不在重载页面;.stop:阻止单击事件冒泡;.self:当事件发生在该元素本身而不是子元素的时候回触发;.capture:事件侦听,事件发生的时候回调用

    ⑦v-on可以绑定多个方法
    ⑧vue中key值得作用
    当vue.js用v-for正在更新已渲染过得元素列表时,它就默认的”就地复用“策略。如果数据的顺序被改变,vue将不会移动DOM元素来匹配数据项的顺序,而是简单复用此处的每个元素,并且确保它在特定的索引下显示已被渲染过得每个元素。key的作用主要是为了更高效的更新虚拟DOM
    ⑨什么是vue的计算属性
    答:在模板中放入了太多的逻辑会让模板过重难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。
    好处:1)使得数据处理结构清晰
    2)依赖于数据,数据更新,处理结果自动更新
    3)计算属性内部this指向vm实例
    4)在template调用时,直接写计算属性名即可
    5)常用的getter方法,获取数据,也可以使用set方法改编数据
    6)methods,不管依赖的数据变不变,methods都会重新技术,但是依赖的数据不变的时候computed从缓存中获取,不会重新计算
    10、vue等页面应用及其优缺点
    vue的目标是通过尽可能简单的api实现响应的数据绑定和组合的视图组件。核心是一个相应的数据绑定系统。MVVM、数据驱动、组件化、轻量化、简洁高效快速,模块友好。
    缺点:不支持低版本浏览器(其实这也是优点,有助于推动浏览器厂商的标准化)不利于SEO的优化。如果要支持SEO,需要通过服务端来进行渲染组件。;第一次加载首页耗时相对长一些。不能使用导航按钮需要自行实现前进后退



  • JS常见问题汇总

    vue.min.js:6 Uncaught TypeError: Assignment to constant variable.

    const定义的常量不能被修改

                    const priceTotal = 0
                    const prudctCount = 0
                    this.package1.forEach(element => {
                        console.log(element,'===element')
                        priceTotal += element.price
                        // prudctCount += element.count
                    });
    修改为 var

  • 公众号与小程序的区别

     

    作者:微动天下
    链接:https://www.zhihu.com/question/53845035/answer/153364018
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    1、定位不同(公众号服务于营销与信息传递,小程序面向产品与服务)

    公众号主要用于信息的传递实现人与信息的连接,借助H5 能够实现简单的交互,主要以营销和信息传递为主简单的服务为辅,而小程序从功能上与公众号有严格区分(不支持关注、消息推送等营销手段),一方面使得产品与服务不至于淹没在公众号营销信息中,另一方支持公众号、朋友圈、群与小程序之间的互动与导流,使得开发者专心做产品与服务,从而为微信带来大量长尾服务叠加微信自身重度服务打造从社交到信息连接再到服务的生态圈。

    2、实现技术区别(公众号基于H5,小程序基于微信自身开发环境与开发语言)

    小程序是微信内的云端应用(所以无需安装),不是原生App,通过WebSocket 双向通信(保证无需刷新即时通信)、本地缓存(图片与UI 本地缓存降低与服务器交互延时)以及微信底层技术优化实现了接近原生APP 的体验。

    公众号是基于传统H5 开发与运行,传统H5 运行环境是浏览器,微信小程序运行环境并非完整的浏览器,开发过程中用到H5 相关的技术,微信小程序的运行环境是微信基于浏览器内核完全重构的一个内置解析器,针对小程序专门做了优化,配合自己定义的开发语言标准(基于H5 进行了优化),提升了小程序的性能。系统权限方面,微信小程序能够通过微信APP 获得更多的系统权限,比如网络通信状态、数据缓存能力等,在此微信APP 相当于架在原有系统中的新的操作系统,小程序借助微信与系统间接交互,使得能够拥有原生APP 的体验。而这一点恰巧是HTML5 web 应用的不足,导致其主要用于业务逻辑与交互简单的应用中。

    3、功能不同(公众号功能围绕信息展示与营销,小程序面向产品与服务)

    微信与公众号在开发语言、设计规范、营销方式、审核机制等功能方面均有较大不同。公众号是一种账号类型,为用户提供信息与咨询发布平台,提供了一种新的信息传播方式,构建与读者之间更好的沟通与管理模式,结合H5以后公众号也能够提供一些简单交互功能。小程序主要旨在提供服务,相比公众号运行更流畅,能够提供更加复杂的产品与服务。公众号功能主要围绕信息传递与营销展开,小程序对营销功能进行了严格控制以与公众号区别,使得小程序的服务在使用体验与便捷性能够得到提升,不至于淹没在公众号过度营销信息中。

    4、体验上的差别(公众号操作延时较大,小程序体验接近原生App)

    公众号中点击应用功能后顶部出现绿色进度需要等一段时间,对于业务逻辑复杂交互要求高的应用使用起来体验较差。而小程序将会非常流畅几乎无需等待,类似普通APP 操作一样流畅。主要原因是公众号没有本地缓存,所以每次打开都是会请求服务器刷新页面,造成延时较长体验下降,小程序对UI 与图片本地缓存,只需要对服务器请求交互数据,页面切换无需刷新,所以体验能够接近原生APP 的流畅程度。

     

    长尾关键词

    长尾关键词(Long Tail Keyword)是指网站上的非目标关键词但与目标关键词相关的也可以带来搜索流量的组合型关键词
    长尾关键词的特征是比较长,往往是2-3个词组成,甚至是短语,存在于内容页面,除了内容页的标题,还存在于内容中。 搜索量非常少,并且不稳定。 长尾关键词带来的客户,转化为网站产品客户的概率比目标关键词高很多,因为长尾词的目的性更强。 存在大量长尾关键词的大中型网站,其带来的总流量非常大。例如,目标关键词是服装,其长尾关键词可以是男士服装、冬装、户外运动装等。长尾关键词基本属性是:可延伸性,针对性强,范围广。长尾关键词是长尾理论在关键词研究上的延伸。“长尾”具有两个特点:细和长。细,说明长尾是份额很少的市场,在以前这是不被重视的市场;长,说明这些市场虽小,但数量众多。众多的微小市场累积起来就会占据市场中可观的份额——这就是长尾的思想。
  • 总结伪类与伪元素

    熟悉前端的人都会听过css的伪类与伪元素,然而大多数的人都会将这两者混淆。本文从解析伪类与伪元素的含义出发,区分这两者的区别,并且列出大部分伪类与伪元素的具体用法,即使你有用过伪类与伪元素,但里面总有一两个你没见过的吧。

    1.伪类与伪元素

    先说一说为什么css要引入伪元素和伪类,以下是css2.1 Selectors章节中对伪类与伪元素的描述

    CSS introduces the concepts of pseudo-elements and pseudo-classes  to permit formatting based on information that lies outside the document tree.

     

    直译过来就是:css引入伪类和伪元素概念是为了格式化文档树以外的信息。也就是说,伪类和伪元素是用来修饰不在文档树中的部分,比如,一句话中的第一个字母,或者是列表中的第一个元素。下面分别对伪类和伪元素进行解释:

    伪类用于当已有元素处于的某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的。比如说,当用户悬停在指定的元素时,我们可以通过:hover来描述这个元素的状态。虽然它和普通的css类相似,可以为已有的元素添加样式,但是它只有处于dom树无法描述的状态下才能为元素添加样式,所以将其称为伪类。

    伪元素用于创建一些不在文档树中的元素,并为其添加样式。比如说,我们可以通过:before来在一个元素前增加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。

     

    2.伪类与伪元素的区别

    这里通过两个例子来说明两者的区别。

    下面是一个简单的html列表片段:

    如果想要给第一项添加样式,可以在为第一个<li>添加一个类,并在该类中定义对应样式:

    HTML:

    CSS:

    如果不用添加类的方法,我们可以通过给设置第一个<li>的:first-child伪类来为其添加样式。这个时候,被修饰的<li>元素依然处于文档树中。

    HTML:

    CSS:

    下面是另一个简单的html段落片段:

    如果想要给该段落的第一个字母添加样式,可以在第一个字母中包裹一个<span>元素,并设置该span元素的样式:

    HTML:

    CSS:

    如果不创建一个<span>元素,我们可以通过设置<p>的:first-letter伪元素来为其添加样式。这个时候,看起来好像是创建了一个虚拟的<span>元素并添加了样式,但实际上文档树中并不存在这个<span>元素。

    HTML:

    CSS:

     

    从上述例子中可以看出,伪类的操作对象是文档树中已有的元素,而伪元素则创建了一个文档数外的元素。因此,伪类与伪元素的区别在于:有没有创建一个文档树之外的元素。

     

    3.伪元素是使用单冒号还是双冒号?

    CSS3规范中的要求使用双冒号(::)表示伪元素,以此来区分伪元素和伪类,比如::before和::after等伪元素使用双冒号(::),:hover和:active等伪类使用单冒号(:)。除了一些低于IE8版本的浏览器外,大部分浏览器都支持伪元素的双冒号(::)表示方法。

    然而,除了少部分伪元素,如::backdrop必须使用双冒号,大部分伪元素都支持单冒号和双冒号的写法,比如::after,写成:after也可以正确运行。

    对于伪元素是使用单冒号还是双冒号的问题,w3c标准中的描述如下:

    Please note that the new CSS3 way of writing pseudo-elements is to use a double colon, eg a::after { … }, to set them apart from pseudo-classes. You may see this sometimes in CSS. CSS3 however also still allows for single colon pseudo-elements, for the sake of backwards compatibility, and we would advise that you stick with this syntax for the time being.

    大概的意思就是:虽然CSS3标准要求伪元素使用双冒号的写法,但也依然支持单冒号的写法。为了向后兼容,我们建议你在目前还是使用单冒号的写法。

    实际上,伪元素使用单冒号还是双冒号很难说得清谁对谁错,你可以按照个人的喜好来选择某一种写法。

     

    4.伪类与伪元素的具体用法

    这一章以含义解析和例子的方式列出大部分的伪类和伪元素的具体用法。下面是根据用途分类的伪类总结图和根据冒号分类的伪元素总结图:

    伪类

    伪元素

    某些伪类或伪元素仍然处于试验阶段,在使用前建议先在Can I Use等网站查一查其浏览器兼容性。处于试验阶段的伪类或伪元素会在标题中标注。

     

    伪类

    状态

    由于状态伪类的用法大家都十分熟悉,这里就不用例子说明了。

    1 :link

    选择未访问的链接

    2 :visited

    选择已访问的链接

    3 :hover

    选择鼠标指针浮动在其上的元素

    4 :active

    选择活动的链接

    5 :focus

    选择获取焦点的输入字段

     

    结构化

    1 :not

    一个否定伪类,用于匹配不符合参数选择器的元素。

    如下例,除了第一个<li>元素外,其他<li>元素的文本都会变为橙色。

    HTML:

    CSS:

    2 :first-child

    匹配元素的第一个子元素。

    如下例,第一个<li>元素的文本会变为橙色。

    HTML:

    CSS:

    3 : last-child

    匹配元素的最后一个子元素。

    如下例,最后一个<li>元素的文本会变为橙色。

    HTML:

    CSS:

    4 first-of-type

    匹配属于其父元素的首个特定类型的子元素的每个元素。

    如下例,第一个<li>元素和第一个<span>元素的文本会变为橙色。

    HTML:

    CSS:

    5 :last-of-type

    匹配元素的最后一个子元素。

    如下例,最后一个<li>元素的文本会变为橙色。

    HTML:

    CSS:

    6 :nth-child

    :nth-child根据元素的位置匹配一个或者多个元素,它接受一个an+b形式的参数,an+b匹配到的元素示例如下:

    • 1n+0,或n,匹配每一个子元素。
    • 2n+0,或2n,匹配位置为2、4、6、8…的子元素,该表达式与关键字even等价。
    • 2n+1匹配位置为1、3、5、7…的子元素、该表达式与关键字odd等价。
    • 3n+4匹配位置为4、7、10、13…的子元素。

    如下例,有以下HTML列表:

    CSS:

    选择第二个元素,”Beta”会变成橙色:

    选择位置序号是2的倍数的元素,”Beta”, “Delta”, “Zeta”, “kappa”会变成橙色:

    选择位置序号为偶数的元素:

    选择从第6个开始,位置序号是2的倍数的元素,”Zeta”, “Theta”, “Kappa”会变成橙色:

    7 :nth-last-child

    :nth-last-child与:nth-child相似,不同之处在于它是从最后一个子元素开始计数的。

    8 :nth-of-type

    :nth-of-type与nth-child相似,不同之处在于它是只匹配特定类型的元素。

    如下例,第二个<p>元素会变为橙色。

    HTML:

    CSS:

    9 :nth-last-type

    :nth-last-of-type与nth-of-type相似,不同之处在于它是从最后一个子元素开始计数的。

    10 :only-child

    当元素是其父元素中唯一一个子元素时,:only-child匹配该元素。

    HTML:

    CSS:

    11 :only-of-type

    当元素是其父元素中唯一一个特定类型的子元素时,:only-child匹配该元素。

    如下例,第一个ul元素只有一个li类型的元素,该li元素的文本会变为橙色。

    HTML:

    CSS:

    12 :target

    当URL带有锚名称,指向文档内某个具体的元素时,:target匹配该元素。

    如下例,url中的target命中id值为target的article元素,article元素的背景会变为黄色。

    URL:

    http://example.com/#target

    HTML:

    CSS:

    表单相关

    1 :checked

    :checked匹配被选中的input元素,这个input元素包括radio和checkbox。

    如下例,当复选框被选中时,与其相邻的<label>元素的背景会变成黄色。

    HTML:

    CSS:

    2 :default

    :default匹配默认选中的元素,例如:提交按钮总是表单的默认按钮。

    如下例,只有提交按钮的背景变成了黄色。

    HTML:

    CSS:

    3 :disabled

    :disabled匹配禁用的表单元素。

    如下例,被禁用input输入框的透明度会变成50%。

    HTML:

    CSS:

    4 :empty

    :empty匹配没有子元素的元素。如果元素中含有文本节点、HTML元素或者一个空格,则:empty不能匹配这个元素。

    如下例,:empty能匹配的元素会变为黄色。

    第一个元素中有文本节点,所以其背景不会变成黄色;

    第二个元素中有一个空格,有空格则该元素不为空,所以其背景不会变成黄色;

    第三个元素中没有任何内容,所以其背景会变成黄色;

    第四个元素中只有一个注释,此时该元素是空的,所以其背景会变成黄色;

    HTML:

    CSS:

    5 :enabled

    :enabled匹配没有设置disabled属性的表单元素。

    6 :in-range

    :in-range匹配在指定区域内元素。

    如下例,当数字选择器的数字在5到10是,数字选择器的边框会设为绿色。

    HTML:

    CSS:

    7 :out-of-range

    :out-of-range与:in-range相反,它匹配不在指定区域内的元素。

    8 :indeterminate

    indeterminate的英文意思是“不确定的”。当某组中的单选框或复选框还没有选取状态时,:indeterminate匹配该组中所有的单选框或复选框。

    如下例,当下面的一组单选框没有一个处于被选中时,与input相邻的label元素的背景会被设为橙色。

    HTML:

    CSS:

    9 :valid

    :valid匹配条件验证正确的表单元素。

    如下例,当email输入框内的值符合email格式时,输入框的边框会被设为绿色。

    HTML:

    CSS:

    10 :invalid

    :invalid与:valid相反,匹配条件验证错误的表单元素。

    11 :optional

    :optional匹配是具有optional属性的表单元素。当表单元素没有设置为required时,即为optional属性。

    如下例,第一个input的背景不会被设为黄色,第二个input的背景会被设为黄色。

    HTML:

    CSS:

    12 :required

    :required与:optional相反匹配设置了required属性的表单元素。

    13 :read-only

    :read-only匹配设置了只读属性的元素,表单元素可以通过设置“readonly”属性来定义元素只读。

    如下例,input元素的背景会被设为黄色。

    HTML:

    CSS:

    14 :read-write

    :read-write匹配处于编辑状态的元素。input,textarea和设置了contenteditable的HTML元素获取焦点时即处于编辑状态。

    如下例,input输入框和富文本框获取焦点时,背景变成黄色。

    HTML:

    CSS:

    15 :scope(处于试验阶段)

    :scope匹配处于style作用域下的元素。当style没有设置scope属性时,style内的样式会对整个html起作用。

    如下例,第二个section中的元素的文本会变为斜体。

    HTML:

    注:目前支持这个伪类的浏览器只有火狐。

    语言相关

    1 :dir(处于实验阶段)

    :dir匹配指定阅读方向的元素,当HTML元素中设置了dir属性时该伪类才能生效。现时支持的阅读方向有两种:ltr(从左往右)和rtl(从右往左)。目前,只有火狐浏览器支持:dir伪类,并在火狐浏览器中使用时需要添加前缀( -moz-dir() )。

    如下例,p元素中的阿拉伯语(阿拉伯语是从右往左阅读的)文本会变成橙色。

    HTML:

    CSS:

    如下例,p元素中的英语文本会变成蓝色

    HTML:

    CSS:

    2 :lang

    :lang匹配设置了特定语言的元素,设置特定语言可以通过为了HTML元素设置lang=””属性,设置meta元素的charset=””属性,或者是在http头部上设置语言属性。

    实际上,lang=””属性不只可以在html标签上设置,也可以在其他的元素上设置。

    如下例,分别给不同的语言设置不同的引用样式:

    HTML:

    CSS:

    其他

    1 :root

    :root匹配文档的根元素。一般的html文件的根元素是html元素,而SVG或XML文件的根元素则可能是其他元素。

    如下例,将html元素的背景设置为橙色

    2.:fullscreen

    :fullscreen匹配处于全屏模式下的元素。全屏模式不是通过按F11来打开的全屏模式,而是通过Javascript的Fullscreen API来打开的,不同的浏览器有不同的Fullscreen API。目前,:fullscreen需要添加前缀才能使用。

    如下例,当处于全屏模式时,h1元素的背景会变成橙色

    HTML:

    JAVASCRIPT:

    CSS:

     

    伪元素

    1 ::before/:before

    :before在被选元素前插入内容。需要使用content属性来指定要插入的内容。被插入的内容实际上不在文档树中。

    HTML:

    CSS:

    2 ::after/:after

    :after在被元素后插入内容,其用法和特性与:before相似。

    3 ::first-letter/:first-letter

    :first-letter匹配元素中文本的首字母。被修饰的首字母不在文档树中。

    CSS:

    4 ::first-line/:first-line

    :first-line匹配元素中第一行的文本。这个伪元素只能用在块元素中,不能用在内联元素中。

    CSS:

    5 ::selection

    ::selection匹配用户被用户选中或者处于高亮状态的部分。在火狐浏览器使用时需要添加-moz前缀。该伪元素只支持双冒号的形式。

    CSS:

    6 ::placeholder

    ::placeholder匹配占位符的文本,只有元素设置了placeholder属性时,该伪元素才能生效。

    该伪元素不是CSS的标准,它的实现可能在将来会有所改变,所以要决定使用时必须谨慎。

    在一些浏览器中(IE10和Firefox18及其以下版本)会使用单冒号的形式。

    HTML:

    CSS:

    7 ::backdrop(处于试验阶段)

    ::backdrop用于改变全屏模式下的背景颜色,全屏模式的默认颜色为黑色。该伪元素只支持双冒号的形式

    HTML:

    CSS:

    参考文章

    1. An Ultimate Guide To CSS Pseudo-Classes And Pseudo-Elements

    2. CSS伪类与CSS伪元素的区别及由来

    原创文章转载请注明:

    转载自AlloyTeam:http://www.alloyteam.com/2016/05/summary-of-pseudo-classes-and-pseudo-elements/