項目中遇到一些實用/優秀的代碼寫法(雜燴)

實用/優秀的代碼寫法

  • es6 數組Array支持鏈式編程,例子身份證中間幾位用'*'代替,替代了我組長說的substr的基礎寫法。
let identity = '4406831112333456675X';
let result = Array.from(identity).map((v, i) => {
  return (i >= 2 && i < 10 ? '*' : v);
}).join('');
const data = [{a: 1},{b: 2}],
      copy = [ ...data ],
      c = data;
console.log(data === copy); // false
console.log(data === c); // true

[...data, ...copy]; // [{a: 1},{b: 2},{a: 1},{b: 2}]
  •  三目運算符計算多種狀況

應用場景:同一個div經過三種不一樣的字符顯示三種不一樣的背景色,只能在view層寫(不能用if)javascript

function setColor(v){
    return v!==2?(v===3?'blue':(v===1?'green':'white')):'red';
}
console.log(setColor(1),setColor(2),setColor(3),setColor(4),setColor(5))
  •  兩個數組合併成成一個數組並以對象的形式一一對應(Array.reduce解決合併思路)

 注意,return用逗號隔開只返回最後一個值css

var rs = {
    head: ["id", "name"], 
    data: [ [100, "Tom"], [101, "Jane"] ] 
};
// 轉換爲[{"id":100,"name":"Tom"},{"id":101,"name":"Jane"}]
console.log(JSON.stringify(normalize(rs)));
function normalize (rs) {
    return rs.data.map(dataItem => 
        rs.head.reduce((itemResult, itemKey, curIndex) => 
            ((itemResult[itemKey] = dataItem [curIndex]), itemResult)
             // 只返回itemResult,這裏運算兩次但只要逗號後面的結果
        , {})
    );
}

 

set();一旦屬性被從新賦值,此方法被自動調用。
get();一旦屬性被訪問讀取,此方法被自動調用。html

<label>輸入:</label><input type="text" id="demo1"><br/>
<label>輸出:</label> <input type="textarea" id="demo2"></input>

<script>
    let a={};
    let output=[];
    Object.defineProperty(a,'b',{   //給a對象添加b屬性
        set:function(val){
            output['b']=val;
        },
        get:function(){
            return output['b'];
        }
    })
    let demo1=document.querySelector('#demo1');
    let demo2=document.querySelector('#demo2');
    demo1.onkeyup=function(){
        a.b=demo1.value;//給a對象添加b屬性時候,觸發了a的set方法,此時#demo1的value值賦值給output['b']。
        demo2.value=output['b'];
    }
</script>
  •  在ng2中自定義了一個路由攔截的服務並在其設置方法,經過數據庫返回的每一個帳號的登陸權限(實際就是記錄能訪問的路由地址保存在routePath)。下面Array.some(callback)(篩選地址數組this.permissions每個值,是否與callback的return值相等,有一個相等都返回true)String.prototype.includes(string)(字符串是否包含指定的字符串返回true/false)配合使用,來判斷是否有權限訪問
/**
 * 驗證是否有該路由的權限
 * @param url
 */
AuthGuardService.prototype.validPermissions = function (routePath) {
    return this.permissions.some(function (url) {
        return routePath.includes(url);
    });
};
  • 在app作搜索的時候,遇到歷史記錄要作去重操做,ES6提供了新的數據結構Set。它相似於數組,可是成員的值都是惟一的,沒有重複的值。學習地址

Set結構的實例有如下屬性。前端

Set.prototype.constructor:構造函數,默認就是Set函數。vue

Set.prototype.size:返回Set實例的成員總數。相似數組的lengthjava

Set實例的方法分爲兩大類:操做方法(用於操做數據)和遍歷方法(用於遍歷成員)。下面先介紹四個操做方法。css3

add(value):添加某個值,返回Set結構自己。git

delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。es6

has(value):返回一個布爾值,表示該值是否爲Set的成員。github

clear():清除全部成員,沒有返回值。clear()

遍歷方法

keys():返回一個鍵名的遍歷器

values():返回一個鍵值的遍歷器

entries():返回一個鍵值對的遍歷器

forEach():使用回調函數遍歷每一個成員

// Set去重返回的是僞對象{0:{},1:{},length:2}
obj.content = Array.from(new Set(obj.content));
  • 當後端返回字符串,前端要根據對應的字符串取下標誌控制樣式或者什麼的,能夠用簡單的枚舉
enum Index { '未處理', '處理中', '已處理', '否決' };
this.dealIndex = +Index[this.detailJson['abnoHandleStsName']];
  • 同源頁面通訊經過監聽本地存儲storage的變化,去改變頁面狀態。例子當主頁先從接口保存數據,而後打開一個同源不一樣路由的頁面,該頁面至關於一個新的資源文件,不會監聽到其餘同源頁面對全局變量,異步事件傳發的狀態改變的值,只能經過localstorage去通訊。

window.addEventListener('storage', _ => {
  this.isLoad = false;
  this.data = JSON.parse(localStorage.getItem('logChat'));
})
  • (ES7新語法async await)表格系統通常具備導出功能,前端導出通常只會導出當前html上有的東西,後端導出能夠按需導出數據(所有數據等)。實際業務中表格會出現幾萬條甚至更多的表格數據,所有導出就會調用接口並傳導出的條數做爲參數,當後端服務器壓力大的時候,用戶還繼續導出所有數據如({'rows': 9999999}),服務器就可能崩潰了。做爲前端能夠作的是分次查詢導出接口,而不是一次傳9999999這種極端參數。
/**
   * 同步導出每次查詢的結果
   */
  async exportHandler($event) {
    let params = {"first": 0, "rows": 100};
    if (PageInfo.totalPages > 1) {
      try {
        for (var i = 1; i < PageInfo.totalPages; i++) {
          params.first = params.rows * i; // 計算頁數
          let content = await this.qryExportData(params, i);//async await相似promise處理地獄回調的效果
                                                            //這裏不走完下面是不會執行的
          PageInfo.totalContent = PageInfo.totalContent.concat(content);
        }
      } catch (e) {
        $event.done(null, null, true);
        this.msgs = this.tips.error('導出查詢失敗!');
      }

    }
    $event.done($event.grid, PageInfo.totalContent);
  }
  • input[type=file]選擇同一個文件只觸發一次,緣由在於onChange事件同一個文件,不停的選擇,只會觸發一次。

解決方法:

一、不用change。在JS事件監聽選擇事件替代。
二、用change,可是上傳成功後,清除file input 選擇的內容。下次就能夠選擇一樣文件

event.target.value = ""; //清空目標文件
  •  

    獲取元素佔據頁面的全部矩形區域 document.documentElement.getBoundingClientRect

好處:比用style去獲取更高級的方法,在TS中直接這樣寫超爽

const {top, left} = document.documentElement.getBoundingClientRect();
//IE8如下獲取的是一個數組,兼容方法 document.documentElement.getBoundingClientRect()[0];
  • 當面對不能用position的狀況去定位的時候,使用CSS3 calc 和 vh單位 去計算高度配合

注:這個插件被JS代碼控制了定位相關的css樣式,無奈只能用css3,注意兼容性 div 底部固定方法(不用position定位)

Angular2的注意地方

  • 模板變量不能與ngModel的名稱相同,否則會報一個Cannot assign to a reference or variable!(不能賦值給引用或變量!),如下寫法就跪在了這個錯誤,模板變量能夠寫多個
<textarea #cancelText placeholder="請輸入緣由" name="cancelModel" [(ngModel)]="cancelText"></textarea>
  •  Component/Pipe/Directive等只能在一個module引入一次,否則會報一個屢次引入Component的錯誤,但因爲一個組件有可能用到不一樣的模塊下的頁面,每一個頁面又有本身的module(ionic3懶加載必須每一個頁面都有module),解決的辦法在對應的公共 XxComponent.ts文件下注入@NgModule並導出該公共組件的Module。若是公共組件多能夠在公共組件文件夾下建立一個Module文件,把全部Component都導入進去。由於module能夠引入屢次

// 1
<ng-template [ngIf]="true">123</ng-template> // 頁面會正常顯示123

// 2
<ng-content></ng-content>//當使用@ContentChild('content')裝飾器,能夠獲取下面123的值放進頁面,儘管ngIf=false
<ng-template #content [ngIf]="false">123</ng-template>
  • Using useExisting provider(元數據providers添加useExisting配合抽象類,提升代碼可讀性同時提高代碼編譯速度,由於在編譯組件過程當中會把注入的服務所有編譯放在組件類裏)

  • angular4+ 有時候更改了部分組件或文件,經過AOT打包上去後仍是出現瀏覽器緩存問題,嘗試直接在script標籤加上hash值做強制修改文件名的方法,會致使項目上線後,用戶經過地址打開網站新文件並無更新上去,而是要再刷新一次纔會請求服務器拉去最新代碼文件。具體緣由未知

其餘

  • 最近寫公司組件文檔https://1ziton.github.io/primeng-ext/,發現import/export在項目中的一種用法。咱們通常會把全部的公共組件都寫成各自的模塊整理在一個文件夾裏,寫成模塊是爲了方便不一樣的地方調用避免因declarations 2 component的錯誤。同時咱們只向外提供一個接口(路徑,全部公共組件都導入導出到此),讓外來文件導入所需的公共組件只需在這個接口上面找就能夠了,下面就是向外提供的接口模塊,import是爲了統一管理模塊,export是爲了供外界使用。這裏須要注意的地方,primeng-ext這些公共組件有可能被其餘公共組件導入使用,這裏咱們就不能夠這樣導入,緣由是循環引用了,custom-component.module.ts導入你的業務模塊,你的業務模塊又導入custom-component.module.ts裏邊的東西。會出現module找不到的狀況
    import { AutoCompleteModule } from "app/custom-components/custom-components.module";

 

// ---------------------------------------------------------
// | Imports
// ---------------------------------------------------------

// Common of angular
import { NgModule, ModuleWithProviders } from '@angular/core';
//share module
import { CommonModule } from "@angular/common";
import { FormsModule } from "@angular/forms";
import { HttpModule } from "@angular/http";
// primeng
import { DataTableModule } from "app/components/datatable/datatable";
//...

//primeng-ext
import { AutoCompleteModule } from "./_primeng-ext/autocomplete";
import { FileUploadModule } from "./_primeng-ext/fileupload";
import { UICalendarModule } from "./_primeng-ext/calendar/calendar";

// Modules
import { AreaSelectComponent } from "app/custom-components/area-select/area-select.component";
import { AbnormalMoverComponent } from "app/custom-components/abnormal-mover/abnormal-mover-select.component";
//...

// ---------------------------------------------------------
// | Exports
// ---------------------------------------------------------

// Modules
//primeng-ext
export { AutoCompleteModule } from "./_primeng-ext/autocomplete";
export { FileUploadModule } from "./_primeng-ext/fileupload";
export { UICalendarModule } from "./_primeng-ext/calendar/calendar";

// Components
export { EchartsDirective, EchartsModule } from "app/custom-components/echarts/echarts";
export { AreaSelectComponent } from "app/custom-components/area-select/area-select.component";
//...

// Services
export { API } from "app/custom-components/services/api";

// Tokens (eg. global services' config)

// ---------------------------------------------------------
// | Root module
// ---------------------------------------------------------

@NgModule({
  imports: [
    HttpModule,
    CommonModule,
    FormsModule,
    DataTableModule,
    TreeModule,
    //...
  ],
  declarations: [
    UIUpload,
    AreaSelectComponent,
    //...
  ],

  exports: [
    UICalendarModule,
    UIGridModule,
    UIUpload,
    UISelectBoxModule,
    //...
  ],
  providers: [
    AreaService
  ]
})
export class CustomComponentsModule {

}
  • 利用H5新東西Bolb對象,blob 存儲着大量的二進制數據,而且 blob 的 size 和 type 屬性,都會被 file 對象所繼承。項目中用blob做導出excel表的功能
    new Blob([csv], {type: 'text/csv;charset=utf-8;'});
    。在這裏不是說blob怎麼用,而是導出的excel有時候會亂碼,具體下圖收貨人號碼

           解決方法:基於primeNG datatable的源碼擴展的對每一個單元格內的值進行轉換,下圖

          csv +='"' + value + '\ufeff"';  就是解決某些單元格亂碼的關鍵,excel不會由於數據是字符就會自動用文本形式顯示。

data.forEach(function (record, i) {
       csv += '\n';
       for (var i_1 = 0; i_1 < columns.length; i_1++) {
         if (columns[i_1].field && !columns[i_1].hidden) {
            let value = _.get(record, columns[i_1].field, null);
            if (typeof value === 'string') {
               alue = value.replace('"', '""');
            } else if (value === null || value === 'null' || value === 'undefined') {
               value = "";
            }
       csv += '"' + value + '\ufeff"';
       if (i_1 < (columns.length - 1)) {
         csv += ",";
       }
     }
   }
});
相關文章
相關標籤/搜索