2017-08-26 84 views
0

我正在使用angular2。我將一個父組件的數據傳遞給另一個子組件。ngOnChange()在angular2中不能正常工作

<app-datatable-repr [myFilterData]="filterData"></app-datatable-repr> 

filterData是一個對象。

第一次OnChanges檢測到"filterData"的變化,但在第二次ngChange未檢測到"filterData"的變化。

如何解決這個問題?

哈日文件upload.component.ts

import { Component, OnInit } from '@angular/core'; 
import { HarFileServiceService } from '../har-file-service.service'; 

@Component({ 
    selector: 'app-har-file-upload', 
    templateUrl: './har-file-upload.component.html', 
    styleUrls: ['./har-file-upload.component.css'] 
}) 

export class HarFileUploadComponent implements OnInit { 

    constructor(private harFileServiceService:HarFileServiceService) { } 

    ngOnInit() { 
    } 
    filterData:Object = {}; 
    changeListener(event:any){ 
    var that = this; 
    var file = event.target.files[0]; 
    var myReader = new FileReader(); 
    var harFile = this.harFileServiceService; 
    myReader.onload = function(e:any){ 
     var jsonData = JSON.parse(e.target.result); 
     harFile.render(jsonData); 
     that.filterData = harFile.responseFileData; 
     // console.log(that.filterData) 
    } 
    // console.log(file); 
    myReader.readAsText(file); 
    } 
} 

哈日文件service.service.ts

import { Injectable } from '@angular/core'; 
import * as $ from 'jquery'; 

@Injectable() 
export class HarFileServiceService { 
    constructor() { } 
    log:Object = { entries: {} }; 
    totals:Object = {}; 
    pads:Object = {}; 
    left; 
    right; 
    idctr:number = 0; 
    reqCount:number = 0; 
    totalReqSize:number = 0; 
    totalRespSize:number = 0; 
    requestObj:Object = {'resources':[]}; 
    responseFileData:any = {}; 
    render(har: any) { 
     var pageref; 
     var that = this; 
     $.each(har.log.entries, function (index, entries) { 
      console.log(index, entries); 
      var singleReqOb = {}; 
      that.requestObj['resources'].push(singleReqOb); 
      pageref = pageref || entries.pageref; 
      if(entries.pageref === pageref) { 
       that.entry(index, entries); 
      } 
     }); 
     this.responseFileData = this.requestObj; 
     console.log(this.responseFileData); 
    } 
    entry(id:any, entry:any) { 
     id = id || this.idctr++; 
     this.log['entries'][id] = entry; 
     var t = new Date(entry.startedDateTime).getTime(); 
     if(this.left && this.right) { 
      this.left = (this.left < t) ? this.left : t; 
      this.right = (this.right > t) ? this.right : t; 
     } 
     else { 
      this.left = this.right = t; 
     } 
     if(entry.request) { 
      this.request(id, entry.request); 
     } 
     if(entry.response) { 
      this.response(id, entry.response); 
     } 
    } 
    request(id:any, request:any) { 
     if(this.log['entries'][id]) { 
      this.log['entries'][id].request = request; 
     } 
     else { 
      this.log['entries'][id] = { 
       id: id, 
       request: request 
      }; 
     } 
     this._updateRequest(id, request); 
     this.reqCount = this.reqCount + 1; 
     if(request.headersSize && request.headersSize > 0) { 
      this.totalReqSize = this.totalReqSize + request.headersSize; 
     } 
     if(request.bodySize && request.bodySize > 0) { 
      this.totalReqSize = this.totalReqSize + request.bodySize; 
     } 
    } 
    response(id:any, response:any) { 
     if(this.log['entries'][id]) { 
      this.log['entries'][id].response = response; 
      this._updateResponse(id, response); 

      if(response.headersSize && response.headersSize > 0) { 
       this.totalRespSize = this.totalRespSize + response.headersSize; 
      } 
      if(response.bodySize && response.bodySize > 0) { 
       this.totalRespSize = this.totalRespSize + response.bodySize; 
      } 
     } 
     else { 
     } 
    } 
    _updateRequest(id:any, request:any) { 
     var reqObj = this.requestObj['resources'][id]; 
     if(request.url) { 
      reqObj['filePath'] = request.url; 
     } 
    }; 
    _updateResponse(id:any, response:any) { 
     var reqObj = this.requestObj['resources'][id]; 
     var type = response.content.mimeType; 
     var type_0 = type.split("/")[0]; 
     var type_1 = type.split("/")[1]; 
     switch (type_1) { 
      case "javascript": 
      case "x-javascript": 
       reqObj['type'] = 'script'; 
       break; 
      case "css": 
      case "json": 
      case "html":  
       reqObj['type'] = type_1; 
       break; 
      case "x-shockwave-flash": 
       reqObj['type'] = 'flash'; 
       break; 
      default: 
       reqObj['type'] = type; 
       break; 
     } 
     if(type_0 == 'image' || type_0 == 'video'){ 
      reqObj['type'] = type_0; 
      reqObj['type'] = (reqObj['type'] == 'image') ? 'image' : reqObj['type']; 
     } 
     if(response.content && response.content.text) { 
      reqObj['size'] = response.bodySize; 
     }else{ 
      reqObj['size'] = ''; 
     } 
    } 
} 

ngOnChange這裏

import { Component, OnInit , OnChanges, SimpleChanges, Input} from '@angular/core'; 
import * as $ from 'jquery'; 
import 'datatables.net' 
import { HarFileServiceService } from '../har-file-service.service'; 

@Component({ 
    selector: 'app-datatable-repr', 
    templateUrl: './datatable-repr.component.html', 
    styleUrls: ['./datatable-repr.component.css'] 
}) 
export class DatatableReprComponent implements OnInit, OnChanges { 
    @Input() myFilterData; 
    constructor(private harFileServiceService:HarFileServiceService) { } 
    public tableWidget: any; 
    ngOnInit() { 
    this.initDatatable(); 
    } 

    ngOnChanges(changes:SimpleChanges){ 
    if(changes.myFilterData.currentValue.hasOwnProperty('resources')){ 
     this.tableWidget.clear().draw(); 
     this.tableWidget.rows.add(changes.myFilterData.currentValue.resources); // Add new data 
     this.tableWidget.columns.adjust().draw(); // Redraw the DataTable 
    } 
    } 
    private truncate(string:any, len:any){ 
    if (string.length > len) 
     return string.substring(0,len)+'...'; 
    else 
     return string; 
    }; 
    parseURL(url:any) { 
     var parsed_url:any = {} 
     if (url == null || url.length == 0) return parsed_url; 
    var protocol_i = url.indexOf('://'); 
    parsed_url.protocol = url.substr(0, protocol_i); 
     var remaining_url = url.substr(protocol_i + 3, url.length); 
     var domain_i = remaining_url.indexOf('/'); 
     domain_i = domain_i == -1 ? remaining_url.length - 1 : domain_i; 
     parsed_url.domain = remaining_url.substr(0, domain_i); 
     parsed_url.path = domain_i == -1 || domain_i + 1 == remaining_url.length ? 
      null : remaining_url.substr(domain_i + 1, remaining_url.length); 
     var domain_parts = parsed_url.domain.split('.'); 
     switch (domain_parts.length) { 
      case 2: 
       parsed_url.subdomain = null; 
       parsed_url.host = domain_parts[0]; 
       parsed_url.tld = domain_parts[1]; 
       break; 
      case 3: 
       parsed_url.subdomain = domain_parts[0]; 
       parsed_url.host = domain_parts[1]; 
       parsed_url.tld = domain_parts[2]; 
       break; 
      case 4: 
       parsed_url.subdomain = domain_parts[0]; 
       parsed_url.host = domain_parts[1]; 
       parsed_url.tld = domain_parts[2] + '.' + domain_parts[3]; 
       break; 
     } 
     parsed_url.parent_domain = parsed_url.host + '.' + parsed_url.tld; 
     return parsed_url; 
    } 
    imgExt:any = ["png", "gif", "jpeg", "jpg"] 
    vidExt:any = ["mov", "flv", "mpg", "mpeg", "mp4", "ogv", "webm"] 
    private initDatatable(): void { 
    var myData = this.myFilterData.hasOwnProperty('responseFileData') ? this.myFilterData.hasOwnProperty('responseFileData') : {}; 
    var that = this; 
    let exampleId: any = $('#resourcesListing'); 
    this.tableWidget = exampleId.DataTable({ 
     aLengthMenu : [], 
      aaData: myData, 
      bPaginate: false, 
      bAutoWidth: false, 
      order: [], 
      language: { 
       search: "Search Resources : ", 
       lengthMenu: "Display _MENU_ Resources", 
       infoFiltered: "(filtered from _MAX_ Resources)", 
       info: "Showing _START_ to _END_ of _TOTAL_ Resources", 
       infoEmpty: "", 
       zeroRecords: "<div style='padding: 10px;'>No resources match your search criteria.</div>", 
       emptyTable: "<div style='padding: 10px;'>No resources available.</div>", 
       paginate: { 
        first: " <i class='fa fa-fast-backward'></i> ", 
        previous: " <i class='fa fa-backward'></i> ", 
        next: " <i class='fa fa-forward'></i> ", 
        last: " <i class='fa fa-fast-forward'></i> " 
       } 
      }, 
     aoColumns: [ 
       { 
        mDataProp: 'filePath', 
        mRender: function (data, type, full) { 
      var urlinfo = (that.parseURL(data));; 
         return that.truncate(urlinfo.domain, 50); 
        }, 
        sWidth: "200px" 
       }, 
       { 
        mDataProp: 'filePath', 
        mRender: function (data, type, full) { 
      var urlinfo = (that.parseURL(data)); 
         return "<a target='_blank' href='"+data+"'/>" + that.truncate(urlinfo.path ? urlinfo.path.split("?")[0] : "", 60) + "</a>"; 
      }, 
      sWidth: "400px" 
       }, 
       // { 
       // mData: "filePath", 
       // mRender: function (data, type, full) { 
       //  return '<a href="#" class="info"><i class="fa fa-info" aria-hidden="true"></i></a>'; 
       // }, 
       // sWidth: "60px", 
       // sClass: "center" 
       // }, 
       { 
        mData: "type", 
        sWidth: "100px", 
        mRender: function (data, type, full) { 
         var resType = data, 
          resPath = full['filePath']; 
         if(resType == "css"){ 
          // background-url will have type css, change to bg-img 
          var ext = resPath.split('.').pop(); 
          if(that.imgExt.indexOf(ext) >= 0){ 
           // showResType = "bg-img"; 
           resType = "bg-image"; 
          } 
         }else if(resType == "other" || resType == ""){ 
          // video comes as type 'other' in firefox and empty in chrome 
          var ext = resPath.split('.').pop(); 
          if(that.vidExt.indexOf(ext) >= 0){ 
           // showResType = "video"; 
           resType = "video"; 
          } 
         }else if(resType == "img"){ 
          resType = "image"; 
         } 
         return resType; 
        } 
       }, 
       { 
        mDataProp: 'filePath', 
        mRender: function (data, type, full) { 
         return (full.type == "image" || full.type == "img") ? '<div class="imageBackgroundParent"><div class="imageBackground" style="background-image: url('+ data +');"></div></div>' : ""; 
        }, 
        sWidth: "120px", 
        sClass: "center" 
       }, 
       { 
        mData: "size", 
        sWidth: "80px" 
       } 
      ], 
    }); 
    } 
} 

的sampleData

"resources":[ 
    { 
    "filePath": "http://www.cricbuzz.com/live-cricket-scores/18460/sl-vs-ind-2nd-test-india-tour-of-sri-lanka-2017", 
    "type": "html", 
    "size": 119362 
    }, 
    { 
    "filePath": "http://gc.kis.v2.scr.kaspersky-labs.com/EAA2612E-9291-A04E-A659-D0B272EEC835/main.js", 
    "type": "script", 
    "size": 104685 
    }, 
    { 
    "filePath": "http://i.cricketcb.com/statics/site/images/cbz-logo.png", 
    "type": "image", 
    "size": 0 
    } 
] 
+0

你更新只是'filterData'裏面的財產?你可以收到完整的代碼 – Aravind

+0

我在問題@Aravind中添加了代碼。 – Kallis

+0

當你說'ngOnChanges'時,你是說變化檢測器沒有檢測到變化嗎? Bc我沒有看到你在任何地方使用ngOnChanges方法。 – diopside

回答

2

因爲對象是可變的ngOnChange()不會被調用。 發生這種情況是因爲ngOnChange()僅在參數實例更改時觸發(而不是其中一個屬性)。

你可以閱讀更多關於它here

你所能採取是不可變對象的優勢。這意味着對象不能改變。有一個名爲immutable.js by facebook的偉大圖書館。您可以使用Object.assign()。當你使用它時,你正在創建對象的新實例(而不是改變引用)。

因此,爲了使長話短說,

constructor(private harFileServiceService:HarFileServiceService) { } 

    ngOnInit() { 
    } 
    filterData:Object = {}; 
    changeListener(event:any){ 
    var file = event.target.files[0]; 
    var myReader = new FileReader(); 
    var harFile = this.harFileServiceService; 
    myReader.onload = (e:any)=>{ 
     var jsonData = JSON.parse(e.target.result); 
     harFile.render(jsonData); 
     this.filterData = Object.assign({},harFile.responseFileData); 
    } 
    // console.log(file); 
    myReader.readAsText(file); 
    } 
} 

在上面的例子中,我使用的Object.assign()。此外,我已經改變了一點語法,並使用'ecmascript arrow function

1

或者使用lodashcloneDeep更改參考

this.filterData = _.cloneDeep(harFile.responseFileData); 
+0

我會檢查@Aravind。 – Kallis

+0

是如何工作的@aravind你能解釋一下你的答案多一點吧。 –

+0

@PardeepJain當您使用'object.assign'它會改變由onChanges的對象有參考將聽取在子組件。事件'cloneDeep'遞歸 – Aravind

相關問題