首页

由‘==’和‘===’引出的js的隐式转换问题

周周

‘==’和‘===’都是Javascript中的比较运算符,都是比较运算符两边是否相等。对于‘==’和‘===’的区别,大家也都知道:

  ‘==’仅仅是比较运算符两边的数值是否相等,如果数值相等则返回true;‘===’不仅会判断运算符两边的数值是否相等,并且还会判断两边的类型是否相等,只有数值和类型都相等才会返回true。虽然知道以上的判断依据已经能解决绝大数此类问题,但是如果往其中深究来说,会有同学问:在比较的时候‘===’先判断类型,如果类型不同就直接返回false,这个没什么问题。但是如果是‘==’比较两个不同类型的数据时,具体是怎么进行计算判断的呢?

 既然是不同类型进行比较,肯定最终参与比较的结果必须是同一个类型的,因此JS会存在一个隐式转换的问题,并且很多JS的隐式转换很难通过console.log()等方法直观的观察到,因此很多初学者会对JS的隐式转换感到疑惑。

 首先让我们回忆一下,咱们的JS中一共有哪些数据类型?

       六大数据类型
       基本数据类型(简单数据类型)
       number 数值型(NaN)
       string 字符串
       boolean 布尔型
       undefined 未定义
       null 空引用
       引用数据类型(复杂数据类型)
       object

       JS基础中,我们学习到咱们的JS中一共有六种数据类型,分为基本数据类型(简单数据类型)和引用数据类型(复杂数据类型),不同类型的值进行比较的时候,存在隐式转换的问题,咱们通过‘==’来验证一下JS隐式转换的情况。

       1.我们首先来看看下列的语句计算结果:

console.log(NaN==true);//false
console.log(NaN==false);//false
console.log(NaN==0);//false
console.log(NaN==1);//false
console.log(NaN==NaN);//false

       由上面的例子可以看出,NaN属于Number数据类型中一个特殊情况,如果‘==’两边同为Number数据类型的数字,很直观的可以看出值是否相同一眼就可以看出结果,但是作为Number类型的特殊情况,NaN在进行比较的时候,也会有特殊的结果:如果 x 或 y 中有一个为 NaN,则返回 false;

       2.我们继续看看下列的语句计算结果:

console.log(null == undefined); //true(特殊情况)---------------------------------
console.log(null == ''); //false
console.log(undefined == ''); //false

      在上述例子中,引出了一个null,null是一个简单数据类型,它的意义就是一个空应用,但是你如果通过console.log(typeof null) 来打印结果的时候却发现,结果竟然是object?此时你可能会怀疑人生,然后疯狂的翻阅之前学习的资料,因为object明明是一个复杂数据类型,怎么会在判断null这个简单数据类型的类型时打印出来呢?其实,这个问题属于一个历史问题。咱们学习的JS在发展过程中是通过ECMAScript来确定规范的,每年都会有新的规定和规范提出,在JS的发展过程中,null一开始的作用就是用来指向一个空地址,让开发者在创建数据的时候,先用null赋值给还未给值的对象用于标准初始化。但是其实咱们开发过程中很少用到,但是这个仍作为规范留了下来。又因为typeof是根据数据的前几位判断数据类型的,null相当于空指针,前几位是地址的格式,所以判断结果就为object。又因为undefined值是派生自null值的,因此ECMA-262规定对他们的相等测试要返回true。所以这一情况判断的条件为:如果 x 与 y 皆为 null 或 undefined 中的一种类型,则返回 true(null == undefined // true);否则返回 false(null == 0 // false);

       3.请看下列例子:

console.log(true == '123'); //false
console.log(true == '1'); //true
console.log(false == '0'); //true
 
console.log(true == !0); //true
 
console.log([] == []); //false
console.log([] == ![]); //true 比较地址 ------------------------------------------------
var a = c = [];
var b = [];
console.log(a == b); //false
console.log(a == !b); //true
console.log(a == c); //true
 
console.log(Boolean([]) == true); //true
console.log(Number([]) == 0); //true
console.log(Number(false) == 0); //true

       其实比较的逻辑为:如果 x,y 类型不一致,且 x,y 为 String、Number、Boolean 中的某一类型,则将 x,y 使用 Number 函数转化为 Number 类型再进行比较;

      使用Number函数可以将其他的数据类型转变为Number类型,这一同为Number类型的数据,对比起来就会变得十分简单。值得注意的是在上述的例子中,两个空数组进行比较,结果返回的结果仍然为false,这个是怎么回事呢?其实这个很好理解,因为数组也是对象的一种,是复杂数据类型,所以用变量储存对象时储存的其实是地址。对象的内容相同,但是储存在堆区的位置不同,所以地址也是不同的,所以在判断的时候返回的是false。

      其实在JS中还有很多的隐式转换情况,以上只是针对于‘==’的隐式转换情况,对于这些问题,在实际开发过程中,需要作为开发者不断的学习和积累,这也是咱们作为开发者的一个要求之一。

根据json文件生成动态菜单

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

[plain] view plain copy
  1. <span style="font-family:SimSun;font-size:16px;">admin.json</span>  
[plain] view plain copy
  1. <span style="font-family:SimSun;font-size:16px;">[  
  2.     {  
  3.         "image": "glyphicon glyphicon-home",//菜单前的图标  
  4.         "name": "设备管理",  
  5.         "submenu": [  
  6.             {  
  7.                 "image": "glyphicon glyphicon-cloud",  
  8.                 "name": "设备分类",  
  9.                 "submenu": [  
  10.                     {  
  11.                         "image": "glyphicon glyphicon-off",  
  12.                         "name": "电源管理",  
  13.                         "url": "html/Node/creditCardPower.html"  
  14.                     },  
  15.                     {  
  16.                             "image": "glyphicon glyphicon-lock",  
  17.                         "name": "门禁管理",  
  18.                         "url": "html/Guard/guardList.html"  
  19.                     },  
  20.                     {  
  21.                         "image": "glyphicon glyphicon-folder-open",  
  22.                         "name": "物品管理",  
  23.                         "url": "html/goods/goodsList.html"  
  24.                     },  
  25.                     {  
  26.                         "image": "glyphicon glyphicon-facetime-video",  
  27.                         "name": "视频管理",  
  28.                         "url": "html/monitor/monitorList.html"  
  29.                     }  
  30.                 ]  
  31.             }  
  32.         ]  
  33.     },  
  34.     {  
  35.         "image": "glyphicon glyphicon-cog",  
  36.         "name": "系统设置",  
  37.         "submenu": [  
  38.             {  
  39.                 "image": "glyphicon glyphicon-heart",  
  40.                 "name": "用户管理",  
  41.                 "submenu": [  
  42.                     {  
  43.                         "image": "glyphicon glyphicon-align-justify",  
  44.                         "name": "用户列表",  
  45.                         "url": "html/User/userList.html"  
  46.                     },  
  47.                     {  
  48.                         "image": "glyphicon glyphicon-random",  
  49.                         "name": "组织机构",  
  50.                         "url": "html/dept/framework.html"  
  51.                     }  
  52.                 ]  
  53.             },  
  54.             {  
  55.                 "image": "glyphicon glyphicon-wrench",  
  56.                 "name": "设备管理",  
  57.                 "submenu": [  
  58.                     {  
  59.                         "image": "glyphicon glyphicon-edit",  
  60.                         "name": "设备参数",  
  61.                         "url": "html/Device/DeviceList.html"  
  62.                     },  
  63.                     {  
  64.                         "image": "glyphicon glyphicon-edit",  
  65.                         "name": "物品库",  
  66.                         "url": "html/equgoods/equGoodsList.html"  
  67.                     }  
  68.                 ]  
  69.             }  
  70.         ]  
  71.     },  
  72.     {  
  73.         "image": "glyphicon glyphicon-list",  
  74.         "name": "日志管理",  
  75.         "submenu": [  
  76.             {  
  77.                 "image": "glyphicon glyphicon-list-alt",  
  78.                 "name": "登入日志",  
  79.                 "url": "html/Log/loginlog.html"  
  80.             },  
  81.             {  
  82.                 "image": "glyphicon glyphicon-tag",  
  83.                 "name": "设备日志",  
  84.                 "url": "html/Log/hardwarelog.html"  
  85.             }  
  86.         ]  
  87.     },  
  88.     {  
  89.         "image":"glyphicon glyphicon-list",  
  90.         "name":"设备管理",  
  91.         "submenu":[  
  92.             {  
  93.             "image":"glyphicon glyphicon-list-alt",  
  94.             "name":"设备管理",  
  95.             "url":"html/mechanism/mechanism.html"  
  96.             }  
  97.         ]  
  98.     }  
  99. ]</span>  

2、读取json文件的service层实现

[java] view plain copy
  1. <span style="font-size:16px;">package com.dskj.service.impl;  
  2.   
  3. import java.io.File;  
  4. import java.util.Scanner;  
  5. import org.springframework.beans.factory.annotation.Value;  
  6. import org.springframework.core.io.Resource;  
  7. import org.springframework.stereotype.Service;  
  8.   
  9. import com.dskj.common.util.StringUtil;  
  10. import com.dskj.service.ReadJsonService;  
  11.   
  12. @Service  
  13. public class ReadJsonServiceImpl implements ReadJsonService{  
  14.     <span style="color:#ff0000;">@Value(value="classpath:json/admin.json")</span>  
  15.     private Resource dataAdmin;      
  16.     <span style="color:#ff0000;">@Value(value="classpath:json/user.json")</span>  
  17.     private Resource dataUser;    
  18.       
  19.     public String getData(String fileName){       
  20.         if(StringUtil.isEmpty(fileName)){  
  21.             throw new NullPointerException();  
  22.         }  
  23.           
  24.         String jsonData = null;  
  25.           
  26.         try {  
  27.             File file = null;     if(fileName.equals("admin.json")){  
  28.                 file = dataAdmin.getFile();  
  29.             }else{  
  30.                 file = dataUser.getFile();  
  31.             }  
  32.               
  33.             jsonData = this.jsonRead(file);  
  34.               
  35.         } catch (Exception e) {  
  36.            e.printStackTrace();  
  37.         }    
  38.         return jsonData;         
  39.     }  
  40.     /** 
  41.      * 读取文件类容为字符串 
  42.      * @param file 
  43.      * @return 
  44.      */  
  45.       private String jsonRead(File file){  
  46.             Scanner scanner = null;  
  47.             StringBuilder buffer = new StringBuilder();  
  48.             try {  
  49.                 scanner = new Scanner(file, "utf-8");  
  50.                 while (scanner.hasNextLine()) {  
  51.                     buffer.append(scanner.nextLine());  
  52.                 }  
  53.             } catch (Exception e) {  
  54.                   
  55.             } finally {  
  56.                 if (scanner != null) {  
  57.                     scanner.close();  
  58.                 }  
  59.             }  
  60.             return buffer.toString();  
  61.         }  
  62. }</span>  

3、controller对应的代码片段

[java] view plain copy
  1. <span style="font-size:16px;">@RequestMapping("")  
  2.     public ModelAndView main() {  
  3.         ModelAndView model = null;  
  4.         String jsonFileName = null;  
  5.           
  6.         SysUser currentUser = (SysUser) ContextUtil.getSession().getAttribute("currentUser");  
  7.         if ("admin".equals(currentUser.getUsername())) {  
  8.             model = new ModelAndView("header1");  
  9.             jsonFileName = "<span style="color:#ff0000;">admin.json</span>";//根据文件名判断读取具体json文件  
  10.         } else {  
  11.             model = new ModelAndView("headerUser");  
  12.             jsonFileName = "<span style="color:#ff0000;">user.json</span>";</span>/<span style="font-size:16px;">/根据文件名判断读取具体json文件  
  13.   
  14.         }  
  15.           
  16.         String menue = <span style="color:#3333ff;">readJsonServiceImpl.getData</span>(jsonFileName);  
  17.           
  18.         model.addObject("menue", menue);  
  19.         return model;  
  20.   
  21.     }</span>  

4、html页面 将jsonarray转换成js对象

[javascript] view plain copy
  1. <span style="font-size:16px;">$(function() {  
  2.     var menue = JSON.parse('<span style="color:#ff0000;"><%=request.getAttribute("menue")%></span>');  
  3.     console.info(menue);  
  4.     createMenu(menue);//调用下边的方法生成动态菜单</span>  

5、对js对象遍历 $.append动态添加到对应页面

[javascript] view plain copy
  1. <span style="font-size:16px;">function createMenu(menue){  
  2.             /* 一级菜单 */  
  3.             $.each(menue,function(i,v){  
  4.                 var menu1 = '<li class="active"><a href="javaScript:;">';  
  5.                 /* menu1 += '<span class="glyphicon glyphicon-home"></span>'; */  
  6.                 menu1 += '<span class=' + '\'' + v.image + '\'' + '>' + '</span>';  
  7.                 menu1 += '<span style="margin-left: 10px;">' + v.name + '</span><span class="fa arrow"></span>';  
  8.                 menu1 += '</a>';  
  9.                 menu1 += '<ul class="nav nav-second-level nps collapse in">';  
  10.                   
  11.                  /* 二级菜单  */  
  12.                     $.each(v.submenu,function(j,vJ){                      
  13.                         var menu2 = '<li class="active">';  
  14.                         menu2 +=        '<a href="javaScript:;" class="">';  
  15.                         /* menu2 +=         '<span class="glyphicon glyphicon-cloud" style="margin-right: 10px;"></span>'; */  
  16.                         menu2 +=            '<span class=' + '\'' + vJ.image + '\'' + 'style=' + '\'' + 'margin-right: 10px;' + '\'' + '>' + '</span>';  
  17.                         menu2 +=             vJ.name + '<span class="fa arrow "></span>';  
  18.                         menu2 +=        '</a>';  
  19.                         menu2 +=                '<ul class="nav nav-third-level nps collapse in">';                             
  20.                               
  21.                         /* 三级菜单 */  
  22.                         if(vJ.submenu){  
  23.                             $.each(vJ.submenu,function(k,vk){  
  24.                                 var menu3 = '<li>';  
  25.                                 menu3 +=        '<a href="javascript:openUrl(\'' + vk.url + '\')">';  
  26.                                 /* menu3 +=             '<span style="margin-right: 10px;" class="glyphicon glyphicon-off">'; */  
  27.                                 menu3 +=            '<span stype=' + '\'' + 'margin-right: 10px;' + '\'' + 'class=' + '\'' + vk.image + '\'' + '';  
  28.                                 menu3 +=            '</span>'+vk.name;  
  29.                                 menu3 +=        '</a>';  
  30.                                 menu3 +=    '</li>';  
  31.                                   
  32.                                 menu2 += menu3;  
  33.                                       
  34.                             });  
  35.                         }else{  
  36.                             $.each(v.submenu,function(j,vJ){  
  37.                                 var menu4 = '<li>';  
  38.                                 menu4 +=        '<a href="javascript:openUrl(\'' + vJ.url + '\')">';  
  39.                                 /* menu3 +=             '<span style="margin-right: 10px;" class="glyphicon glyphicon-off">'; */  
  40.                                 menu4 +=            '<span stype=' + '\'' + 'margin-right: 10px;' + '\'' + 'class=' + '\'' + vJ.image + '\'' + '';  
  41.                                 menu4 +=            '</span>'+vJ.name;  
  42.                                 menu4 +=        '</a>';  
  43.                                 menu4 +=    '</li>';  
  44.                                       
  45.                                  menu2 = menu4;   
  46.                             });  
  47.                         }  
  48.                             menu1 += menu2;  
  49.                     });  
  50.                       
  51.                     $("#side-menu").append(menu1);  
  52.                 });  
  53.                   
  54.             }</span>  

6、效果如下图

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

jquery原理的简单分析

周周

       jquery是一个轻量级的JS框架,这点相信大部分人都听过,而jquery之所以有这样一个称呼,就是因为它悄悄披了一件外衣,将自己给隐藏了起来。

      /以下截取自jquery源码片段
      (function( window, undefined ) {
      /*    源码内容    */
       })( window );

      上面这一小段代码来自于1.9.0当中jquery的源码,它是一个无污染的JS插件的标准写法,专业名词叫闭包。可以把它简单的看做是一个函数,与普通函数不同的是,这个函数没有名字,而且会立即执行,就像下面这样,会直接弹出字符串。

      (function( window, undefined ) {
         alert("Hello World!");
       })( window );

       可以看出来这样写的直接效果,就相当于我们直接弹出一个字符串。但是不同的是,我们将里面的变量变成了局域变量,这不仅可以提高运行速度,更重要的是我们在引用jquery的JS文件时,不会因为jquery当中的变量太多,而与其它的JS框架的变量命名产生冲突。对于这一点,我们拿以下这一小段代码来说明。

     var temp = "Hello World!";
        (function( window, undefined ) {
         var temp = "ByeBye World!";
        })( window );
        alert(temp);

       这段代码的运行结果是Hello而不是ByeBye,也就是说闭包中的变量声明没有污染到外面的全局变量,倘若我们去掉闭包,则最终的结果会是ByeBye,就像下面这样。

      var temp = "Hello World!";
        //    (function( window, undefined ) {
         var temp = "ByeBye World!";
      //    })( window );
       alert(temp);

       由此就可以看出来,jquery的外衣就是这一层闭包,它是很重要的一个内容,是编写JS框架必须知道的知识,它可以帮助我们隐藏我们的临时变量,降低污染。

       刚才我们说了,jquery将自己声明的变量全部都用外衣遮盖起来了,而我们平时使用的Jquery和$,却是真真实实的全局变量,这个是从何而来,谜底就在jquery的某一行代码,一般是在文件的末尾。

window.jQuery = window.$ = jQuery;
       这一句话将我们在闭包当中定义的jQuery对象导出为全局变量jQuery和$,因此我们才可以在外部直接使用jQuery和$。window是默认的JS上下文环境,因此将对象绑定到window上面,就相当于变成了传统意义上的全局变量,就像下面这一小段代码的效果一样。

      var temp = "Hello World!";
      (function( window, undefined ) {
         var temp = "ByeBye World!";
         window.temp = temp;
       })( window );
       alert(temp);

       很明显,它的结果应该是ByeBye,而不是Hello。因为我们在闭包中导出了temp局部变量为全局变量,从而覆盖了第一行声明的全局变量temp。

        jquery最核心的功能,就是选择器。而选择器简单理解的话,其实就是在DOM文档中,寻找一个DOM对象的工具。

        首先我们进入jquery源码中,可以很容易的找到jquery对象的声明,看过以后会发现,原来我们的jquery对象就是init对象。

         jQuery = function( selector, context ) {
          return new jQuery.fn.init( selector, context, rootjQuery );
         }

         jQuery.fn = jQuery.prototype;

         jQuery.fn.init.prototype = jQuery.fn;
        这两句话,第一句把jQuery对象的原型赋给了fn属性,第二句把jQuery对象的原型又赋给了init对象的原型。也就是说,init对象和jQuery具有相同的原型,因此我们在上面返回的init对象,就与jQuery对象有一样的属性和方法。
很多时候,我们在jQuery和DOM对象之间切换时需要用到[0]这个属性。从截图也可以看出,jQuery对象其实主要就是把原生的DOM对象存在了[0]的位置,并给它加了一系列简便的方法。这个索引0的属性我们可以从一小段代码简单的看一下它的由来,下面是init方法中的一小段对DOMElement对象作为选择器的源码。

      // Handle $(DOMElement)
       if ( selector.nodeType ) {
            /*     可以看到,这里将DOM对象赋给了jQuery对象的[0]这个位置  */
            this.context = this[0] = selector;
            this.length = 1;
           return this;
        }

       这一小段代码可以在jquery源码中找到,它是处理传入的选择参数是一个DOM对象的情况。可以看到,里面很明显的将jQuery对象索引0的位置以及context属性,都赋予了DOM对象。代码不仅说明了这一点,也同时说明了,我们使用$(DOMElement)可以将一个DOM对象转换为jQuery对象,从而通过转换获得jQuery对象的简便方法。

项目总结关于ionic3中的ion-segment的总结

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里


目前做的项目是ionic3和angular4.0的结合,所以用到了很多关于ionic3中封装好的标签,例如具有轮播效果的ion-slides和ion-slide等。那么这次就要总结一下另外一个标签ion-segment的用法了。 
ion-segment这个标签以前用的很少,几乎没有用过。它主要是一组按钮,有时称为分段控件,之前都是用button按钮,现在知道了,开始用ion-segment,因为它有自带的样式,这样就可节省很多时间,同时呢允许用户与许多控件的紧凑组进行交互。 分段提供与标签相似的功能,选择一个将取消选择所有其他选项。 当您希望让用户在应用程序的不同页面之间来回移动时,应使用选项卡栏而不是分段控件。 您可以使用Angular的ngModel或FormBuilder API。 
下面来看一段代码:

Segment 在头部使用

<ion-header> <ion-toolbar> <ion-segment [(ngModel)]="icons" color="secondary"> <ion-segment-button value="camera"> <ion-icon name="camera">带iocn</ion-icon> </ion-segment-button> <ion-segment-button value="bookmark"> 头部使用Segment <ion-icon name="bookmark"></ion-icon> </ion-segment-button> </ion-segment> </ion-toolbar> </ion-header>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Segment 在内容里面使用

<ion-segment [(ngModel)]="relationship" color="primary" (ionChange)="segmentChanged($event)"> <ion-segment-button value="friends"> Segment 在内容里面使用 </ion-segment-button> <ion-segment-button value="enemies"> 可以绑定一个事件(ionChange) </ion-segment-button> </ion-segment>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Segment 在表单里面使用

<form [formGroup]="myForm"> <ion-segment formControlName="mapStyle" color="danger"> <ion-segment-button value="standard"> Standard </ion-segment-button> <ion-segment-button value="hybrid"> 表单内使用 </ion-segment-button> <ion-segment-button value="sat"> Satellite </ion-segment-button> </ion-segment> </form>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
Segment 配合ngSwitch使用
<ion-segment [(ngModel)]="change"> <ion-segment-button value="apple"> 苹果 </ion-segment-button> <ion-segment-button value="pie"></ion-segment-button> </ion-segment> <div [ngSwitch]="change"> <div *ngSwitchCase="'apple'">
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
苹果显示,如果要默认显示一个就把默认的那个设置一个初始值比如要默认显示苹果就把苹果的value值设置成change也就是说,在定义change变量的时候,需要把哪个设置为默认显示就把哪个的value值赋值给change作为初始值 public change=”pie”;


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

css的多行省略号处理

周周

      在我们的页面布局的时候,经常会有这样的需求,超过指定行文本的时候会进行(省略号...)的处理,那么我们改怎么设置css呢?如下:

设置盒子的css为:

  • overflow:hidden;;
  • text-overflow:ellipsis;
  • white-space:nowrap;

       但是这样只能显示一行而不能实现指定行,所以还要其他的方法来实现指定行处理的



     WebKit浏览器或移动端的页面(大部分移动端都是webkit)

        可以直接使用WebKit的CSS扩展属性(WebKit是私有属性)-webkit-line-clamp ;注意:这是一个不规范的属性,它没有出现在 CSS 规范草案中。



        -webkit-line-clamp用来限制在一个块元素显示的文本的行数。 为了实现该效果,它需要组合其他的WebKit属性。
       常见结合属性:
  • display: -webkit-box; 必须结合的属性 ,将对象作为弹性伸缩盒子模型显示 。
  • -webkit-box-orient 必须结合的属性 ,设置或检索伸缩盒对象的子元素的排列方式 。
  • text-overflow: ellipsis;,可以用来多行文本的情况下,用省略号“…”隐藏超出范围的文本 。

     css 代码:

  • overflow:hidden;
  • text-overflow: ellipsis;
  • display: -webkit-box;
  • -webkit-line-clamp:2;/*这里控制着显示多少行*/
  • -webkit-box-orient:vertical;


关于Vuex的全家桶状态管理(一)

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

1:安装

 npm install vuex --save
    
  • 1

2: 在main.js 主入口js里面引用store.js

import Vue from 'vue' import App from './App' import router from './router' import store from './vuex/store' //引用store.js Vue.config.productionTip = false //阻止在启动时生成生产提示 //vue实例 new Vue({
 el: '#app',
 router,
 store, //把store挂在到vue的实例下面 template: '<App/>',
 components: { App }
})
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

3:在store.js里引用Vuex

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) //注册Vuex // 定义常量  如果访问他的话,就叫访问状态对象 const state = {
  count: 1 } // mutations用来改变store状态, 如果访问他的话,就叫访问触发状态 const mutations = { //这里面的方法是用 this.$store.commit('jia') 来触发 jia(state){
    state.count ++
  },
  jian(state){
    state.count --
  },
} //暴露到外面,让其他地方的引用 export default new Vuex.Store({
  state,
  mutations
})
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

4:在vue组件中使用

使用$store.commit(‘jia’)区触发mutations下面的加减方法

<template> <p class="hello"> <h1>Hello Vuex</h1> <h5>{{$store.state.count}}</h5> <p> <button @click="$store.commit('jia')">+</button> <button @click="$store.commit('jian')">-</button> </p> </p> </template> <!-- 加上scoped是css只在这个组件里面生效,为了不影响全局样式 --> <style scoped> h5{ font-size: 20px; color: red; } </style>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

这里写图片描述

5:state访问状态对象

使用computed计算

<template> <p class="hello"> <h1>Hello Vuex</h1> <h5>{{count}}</h5> <p> <button @click="$store.commit('jia')">+</button> <button @click="$store.commit('jian')">-</button> </p> </p> </template> <script> import {mapState} from 'vuex' export default{
  name:'hello', //写上name的作用是,如果你页面报错了,他会提示你是那个页面报的错,很实用 // 方法一 // computed: { //  count(){ //   return this.$store.state.count + 6 //  } // } // 方法二 需要引入外部 mapState computed:mapState({
   count:state => state.count + 10 }) // ECMA5用法 // computed:mapState({ //  count:function(state){ //   return state.count //  } // }) //方法三 // computed: mapState([ //  'count' // ]) } </script>
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

原生js的ajax请求

周周

传统方法的缺点:

      传统的web交互是用户触发一个http请求服务器,然后服务器收到之后,在做出响应到用户,并且返回一个新的页面,,每当服务器处理客户端提交的请求时,客户都只能空闲等待,并且哪怕只是一次很小的交互、只需从服务器端得到很简单的一个数据,都要返回一个完整的HTML页,而用户每次都要浪费时间和带宽去重新读取整个页面。这个做法浪费了许多带宽,由于每次应用的交互都需要向服务器发送请求,应用的响应时间就依赖于服务器的响应时间。这导致了用户界面的响应比本地应用慢得多。

什么是ajax

       ajax的出现,刚好解决了传统方法的缺陷。AJAX 是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

XMLHttpRequest 对象

       XMLHttpRequest对象是ajax的基础,XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。目前所有浏览器都支持XMLHttpRequest

方法
描述
abort()
停止当前请求
getAllResponseHeaders() 
 把HTTP请求的所有响应首部作为键/值对返回
getResponseHeader("header")
返回指定首部的串值
open("method","URL",[asyncFlag],["userName"],["password"])
建立对服务器的调用。method参数可以是GET、POST或PUT。url参数可以是相对URL或绝对URL。这个方法还包括3个可选的参数,是否异步,用户名,密码
send(content)
向服务器发送请求
setRequestHeader("header", "value") 
把指定首部设置为所提供的值。在设置任何首部之前必须先调用open()。设置header并和请求一起发送 ('post'方法一定要 )
五步使用法:

       1.创建XMLHTTPRequest对象
       2.使用open方法设置和服务器的交互信息
       3.设置发送的数据,开始和服务器端交互
       4.注册事件
       5.更新界面

下面给大家列出get请求和post请求的例子

get请求:      

       //步骤一:创建异步对象
       var ajax = new XMLHttpRequest();
       //步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端
       ajax.open('get','getStar.php?starName='+name);
       //步骤三:发送请求
        ajax.send();
       //步骤四:注册事件 onreadystatechange 状态改变就会调用
        ajax.onreadystatechange = function () {
       if (ajax.readyState==4 &&ajax.status==200) {
       //步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
       console.log(xml.responseText);//输入相应的内容
         }
        } 

post请求:

       //创建异步对象  
       var xhr = new XMLHttpRequest();
       //设置请求的类型及url
       //post请求一定要添加请求头才行不然会报错
       xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
       xhr.open('post', '02.post.php' );
       //发送请求
       xhr.send('name=fox&age=18');
       xhr.onreadystatechange = function () {
       // 这步为判断服务器是否正确响应
       if (xhr.readyState == 4 && xhr.status == 200) {
              console.log(xhr.responseText);
             }
        };    

为了方便使用,我们可以把他封装进方法里面,要用的时候,直接调用就好了

       function ajax_method(url,data,method,success) {
       // 异步对象
       var ajax = new XMLHttpRequest();

      // get 跟post  需要分别写不同的代码
      if (method=='get') {
          // get请求
          if (data) {
              // 如果有值
              url+='?';
              url+=data;
          }else{

         }      

       // 设置 方法 以及 url
            ajax.open(method,url);

           // send即可
           ajax.send();
        }else{
             // post请求
             // post请求 url 是不需要改变
             ajax.open(method,url);

            // 需要设置请求报文
           ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded");

           // 判断data send发送数据
          if (data) {
            // 如果有值 从send发送
                ajax.send(data);
          }else{
               // 木有值 直接发送即可
              ajax.send();
            }
         }     

       // 注册事件
       ajax.onreadystatechange = function () {
       // 在事件中 获取数据 并修改界面显示
            if (ajax.readyState==4&&ajax.status==200) {
                // console.log(ajax.responseText);

                // 将 数据 让 外面可以使用
               // return ajax.responseText;

               // 当 onreadystatechange 调用时 说明 数据回来了
              // ajax.responseText;

              // 如果说 外面可以传入一个 function 作为参数 success
              success(ajax.responseText);
             }
         }
      }

关于Vuex的全家桶状态管理(二)

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

1:mutations触发状态 (同步状态)

<template> <p class="hello"> <h1>Hello Vuex</h1> <h5>{{count}}</h5> <p> <button @click="jia">+</button> <button @click="jian">-</button> </p> </p> </template> <script> import {mapState,mapMutations} from 'vuex' export default{
  name:'hello', //写上name的作用是,如果你页面报错了,他会提示你是那个页面报的错,很实用 //方法三 computed: mapState([ 'count' ]),
  methods:{
   ...mapMutations([ 'jia', 'jian' ])
  }
 } </script>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

2:getters计算属性

getter不能使用箭头函数,会改变this的指向

在store.js添加getters

 // 计算 const getters = {
  count(state){ return state.count + 66 }
} export default new Vuex.Store({
  state,
  mutations,
  getters
})
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

//count的参数就是上面定义的state对象 
//getters中定义的方法名称和组件中使用的时候一定是一致的,定义的是count方法,使用的时候也用count,保持一致。 
组件中使用

<script> import {mapState,mapMutations,mapGetters} from 'vuex' export default{
  name:'hello',
  computed: {
   ...mapState([ 'count' ]),
   ...mapGetters([ 'count' ])
  },
  methods:{
   ...mapMutations([ 'jia', 'jian' ])
  }
 } </script>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3:actions (异步状态)

在store.js添加actions

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) // 定义常量 const state = { count: 1 } // mutations用来改变store状态 同步状态 const mutations = {
  jia(state){
    state.count ++
  },
  jian(state){
    state.count --
  },
} // 计算属性 const getters = {
  count(state){ return state.count + 66 }
} // 异步状态 const actions = {
  jiaplus(context){
    context.commit('jia') //调用mutations下面的方法
    setTimeout(()=>{
      context.commit('jian')
    },2000) alert('我先被执行了,然后两秒后调用jian的方法') }, jianplus(context){ context.commit('jian') }
} export default new Vuex.Store({
  state,
  mutations,
  getters,
  actions
})
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

在组件中使用

<template> <p class="hello"> <h1>Hello Vuex</h1> <h5>{{count}}</h5> <p> <button @click="jia">+</button> <button @click="jian">-</button> </p> <p> <button @click="jiaplus">+plus</button> <button @click="jianplus">-plus</button> </p> </p> </template> <script> import {mapState,mapMutations,mapGetters,mapActions} from 'vuex' export default{
  name:'hello',
  computed: {
   ...mapState([ 'count' ]),
   ...mapGetters([ 'count' ])
  },
  methods:{ // 这里是数组的方式触发方法 ...mapMutations([ 'jia', 'jian' ]), // 换一中方式触发方法 用对象的方式 ...mapActions({
    jiaplus: 'jiaplus',
    jianplus: 'jianplus' })
  }
 } </script> <style scoped> h5{ font-size: 20px; color: red; } </style>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

4:modules 模块

适用于非常大的项目,且状态很多的情况下使用,便于管理

修改store.js

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const state = { count: 1 } const mutations = {
  jia(state){
    state.count ++
  },
  jian(state){
    state.count --
  },
} const getters = {
  count(state){ return state.count + 66 }
} const actions = {
  jiaplus(context){
    context.commit('jia') //调用mutations下面的方法
    setTimeout(()=>{
      context.commit('jian')
    },2000) alert('我先被执行了,然后两秒后调用jian的方法') }, jianplus(context){ context.commit('jian') }
}

//module使用模块组的方式 moduleA const moduleA = { state, mutations, getters, actions }

// 模块B moduleB const moduleB = { state: { count:108
  }
} export default new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB,
  }
})
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

JS中作用域的销毁和不销毁的情况总结

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

window全局作用域->页面关掉才销毁
函数执行会形成私有的作用域

1)作用域的销毁
一般情况下,函数执行形成一个私有的作用域,当执行完成后就销毁了->节省内存空间

2)作用域的不立即销毁
function fn(){
var i=10;
return function(n){
console.log(n+i++);
}
}
fn()(15);//->先执行fn,有一个私有的变量i=10,返回一个堆内存地址 xxxfff111,我们发现这个地址还用到了一次,那么当前的这个fn形成私有作用域(A)就不能立即销毁了,xxxfff111(15)->输出25,A中的i变为11;当xxxfff111执行完了,发现这个地址没用了,浏览器就把A、xxxfff111都释放了

fn()(20);//->在执行fn的时候一切都从新开始了,和上面的步骤是一样的->输出30

3)作用域的不销毁:形成一个私有作用域,里面的内容被外面占用了
function fn(){
var i=10;
return function(n){
console.log(n+i++);
}
}
var f=fn();//->fn执行形成一个私有的作用域A,A中有一个私有的变量i=10,A中返回一个地址xxxfff11,被外面的f占用了,那么当前的A就不能销毁了
f(15);//->输出25,让A中的i=11
f(20);//->输出31,让A中的i=12

当我们知道f用完的时候,为了优化性能,我们让f=null,这样的话A中的xxxfff111没人占用了,浏览器会把A和xxxfff111都释放了


几种不销毁常用到的形式:
1)函数执行,返回一个引用数据类型的值,并且在函数的外面被别人接收了,那么当前函数形成的私有作用域就不在销毁了–>例如上面的案例

2)在函数执行的时候,里面的一个小函数的地址赋值给了我们的外面元素的点击事件,那么当前小函数也相当于被外面占用了,大函数执行形成的私有的作用域也不销毁了
//每一次循环都执行自执行函数形成一个私有的作用域(循环三次就有三个作用域,每一个作用域中都有一个i,第一个存储的是0,第二个存数的是1..),在每一个私有的作用域中都把里面的函数绑定给了外面元素的点击事件,这样的话每一次形成的作用域都不销毁了(三个不销毁的作用域)
var oLis=document.getElementsByTagName(“li”);
for(var i=0;i<oLis.length;i++){
~function(i){
oLis[i].onclick=function(){
tabChange(i);
}
}(i);
}

3)在使用setTimeout实现轮询动画的时候,我们如果move需要传递参数值,那么像下面这样的写法会行成很多的不销毁的作用域,非常的耗性能
function move(tar){
<js code>

//window.setTimeout(move,10); ->第二次执行move的时候我们没有给它传值(这样写不行)
window.setTimeout(function(){
move(tar);
},10);//->这样写实现了,但是每一次执行定时器都会形成一个私有的所用域(匿名函数形成的)A,在A中使用了上级作用域中的tar的值,而且执行了move又形成了一个小的作用域(而在小的作用域中会使用tar的值),这样每一次定时器形成的A都不能销毁了
}
move(100);//->第一次这样执行传递100

//解决办法:
function move(tar){
~function _move(){
<js code>
window.setTimeout(_move,10);
}();
}
move(100);//->第一次这样执行传递100


JS中内存空间释放的问题(堆内存、栈内存)
[谷歌浏览器]
我们开辟一个内存,可能或有一些其他的变量等占用了这个内存,谷歌浏览器都会间隔一段时间看这个内存还有没有被占用,如果发现有没有被占用的内存了,就自己帮我们回收了(内存释放)

[火狐和IE]
我们开个内存,当我们引用了它,就在内存中记录一个数,增加一个引用浏览器就把这个数+1,减少一个引用,浏览器就把这个数-1…当减到零的时候浏览器就把这个内存释放了;但是有些情况下(尤其是IE)记着记着就弄乱了,内存就不能释放了–>浏览器的内存泄露

var obj={};
我们养成一个好的习惯,当我们obj这个对象使用完成了,我们手动的obj=null (null空对象指针),浏览器会自己把刚才的堆内存释放掉


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

前端常用class命名

周周

头:header

内容:content/container

尾:footer

导航:nav

侧边栏:sidebar

栏目:column

页面外围控制整体布局宽度:wrapper

左中右:left center right

登录条:loginbar

标志:logo

版心:banner

页面主体:main

热点:hot

新闻:news

下载:download

子导航:subnav

菜单:menu

子菜单:submenu

搜索:search

友情链接:friendlink

页脚:footer

版权:copyright

滚动:scroll

标签页:tab

文章列表:list

提示信息:msg

小技巧:tips

栏目标题:title

加入:joinUS

指南:guide

服务:service

注册:regsiter

状态:status

投票:vote

合作伙伴:partner

日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档