angular11源碼探索二[Renderer2]

其實我經過這段時間的深刻學習,已經寫到第6,7篇的,天天晚上都熬夜很晚,我發現了angular的寶貴東西,也慢慢明白了這個好東西,因爲第一篇我的寫的質量比較高,後面寫的質量不高,感受有點初級,一直沒發,本身也開始迷茫了,研究源碼的目標是爲了什麼,啃源碼是一個很迷茫很打擊自信有挑戰性的東西,須要要一堆迷迷糊糊的東西去理解本質,加上前面幾個月沒怎麼深刻angular致使不少東西也忘記了,本身也是抱着一個初學者的態度去探究源碼,已經編寫的質量一直達不到本身的要求,可是我編寫的一些東西,都是抱着初學者的態度去理解的,對於解決問題和從實際問題去理解angular仍是有很大幫助的css

技術成長分爲三個階段:html

第一階段:化難爲易node

第二階段:由易變難api

第三階段:分割難易app

本身的編寫的時候是否是應該先作個第一階段的事,理解怎麼能全面的去,精通這個api,官網上面的介紹,說實例有點淺,本身能不能作到,遇到這個api基本能理解所有的方法,相信本身能編寫20篇事後的質量可能有明顯的提升,因此急不來,慢慢來,別過於抱着目的性去弄,有時候遇到太難的問題,容易致使心態崩潰,能夠跟之前同樣,從源碼的基礎上去啃透這個api,但願將來的本身能變得更強,學東西仍是儘可能讓本身變得更加自信...dom

Renderer2

<div data="[1,2,3]" #apps>121212</div>

export class UserComponent implements OnInit ,AfterViewInit{
  @ViewChild('apps') ages:ElementRef;

  constructor(private kvDiffers: KeyValueDiffers, private http: HttpClient,private renderer:Renderer2) {}

ngAfterViewInit() {
// 建立dom
  let app = this.renderer.createElement('div');
 // 建立文本
  let text = this.renderer.createText('大帥比');
  // 建立註釋
  let com=this.renderer.createComment('我是註釋')
  
  //添加建立的dom
  this.renderer.appendChild(this.ages.nativeElement,app)
  //添加建立的文字
  this.renderer.appendChild(this.ages.nativeElement,text)
  this.renderer.appendChild(this.ages.nativeElement,com)
}
}

insertBefore

this.renderer.insertBefore(父節點,要添加的子節點newChild,現節點前面添加newChild,isMove:boolean  是否觸發動畫)

removeChild

this.renderer.removeChild(父節點,刪除的子節點,)

刪除全部子節點svg

const childElements = this.el.nativeElement.children;
for (let child of childElements) {
  this.renderer.removeChild(this.el.nativeElement, child);
}

源碼地址

\packages\platform-browser\src\dom\dom_renderer.tsoop

createElement

export const NAMESPACE_URIS: {[ns: string]: string} = {
  'svg': 'http://www.w3.org/2000/svg',
  'xhtml': 'http://www.w3.org/1999/xhtml',
  'xlink': 'http://www.w3.org/1999/xlink',
  'xml': 'http://www.w3.org/XML/1998/namespace',
  'xmlns': 'http://www.w3.org/2000/xmlns/',
};

createElement(name: string, namespace?: string): any {
    if (namespace) {
      // 命名空間,我的以爲沒多大用處
      return document.createElementNS(NAMESPACE_URIS[namespace] || namespace, name);
    }
    return document.createElement(name);
  }

// 建立文本
  createText(value: string): any {
    return document.createTextNode(value);
  }
// 添加dom   ,父節點        子節點
  appendChild(parent: any, newChild: any): void {
    parent.appendChild(newChild);
  }
// 插入節點,    父節點      新的子節點        現有的前面插入(新的子節點)
  insertBefore(parent: any, newChild: any, refChild: any): void {
    if (parent) {
      parent.insertBefore(newChild, refChild);
    }
  }
// 父節點直接刪除子節點
  removeChild(parent: any, oldChild: any): void {
    if (parent) {
      parent.removeChild(oldChild);
    }
  }
// 臥槽居然原生裏面能夠創造出,註釋
  createComment(value: string): any {
    return document.createComment(value);
  }

剩下的幾個屬性

//父節點  
parentNode(node: any): any {
    return node.parentNode;
  }
// 下一個兄弟節點
  nextSibling(node: any): any {
    return node.nextSibling;
  }
// 設置
  setAttribute(el: any, name: string, value: string, namespace?: string): void {
      // 有命令空間
    if (namespace) {
     ...
    } else {
      el.setAttribute(name, value);
    }
  }
// 刪除屬性
  removeAttribute(el: any, name: string, namespace?: string): void {
    // 有命令空間的刪去
      if (namespace) {
  	... 
    } else {
      el.removeAttribute(name);
    }
  }
// 添加class
  addClass(el: any, name: string): void {
    el.classList.add(name);
  }
// 刪除class
  removeClass(el: any, name: string): void {
    el.classList.remove(name);
  }
export enum RendererStyleFlags2 {
  Important = 1 << 0,
      // 1
  DashCase = 1 << 1
      // 2
}


setStyle(el: any, style: string, value: any, flags: RendererStyleFlags2): void {
    if (flags & (RendererStyleFlags2.DashCase | RendererStyleFlags2.Important)) {
      el.style.setProperty(style, value, flags & RendererStyleFlags2.Important ? 'important' : '');
    } else {
      el.style[style] = value;
    }
  }

  removeStyle(el: any, style: string, flags: RendererStyleFlags2): void {
    if (flags & RendererStyleFlags2.DashCase) {
      el.style.removeProperty(style);
    } else {
      // IE 狀況下 null爲刪除樣式
      el.style[style] = '';
    }
  }

第四個參數是可選參數,默認是添加優先級學習

this.renderer.setStyle(a,'background','red',1) //添加優先級,2是取消優先級
也可使用枚舉的形式
    this.renderer.setStyle(a,'background','red',RendererStyleFlags2.Important) 
也能夠直接在第三個參數上添加
 this.renderer.setStyle(a,'background','red!important')

setProperty

修改內置屬性動畫

// 搖擺樹的內容暫時不太懂
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;

setProperty(el: any, name: string, value: any): void {
    NG_DEV_MODE && checkNoSyntheticProp(name, 'property');
    el[name] = value;
  }

const AT_CHARCODE = (() => '@'.charCodeAt(0))();
const AT_CHARCODE =  '@'.charCodeAt(0);
// 思考這兩種寫法有什麼區別...
function checkNoSyntheticProp(name: string, nameKind: string) {
  if (name.charCodeAt(0) === AT_CHARCODE) {
    throw new Error(`Found the synthetic ${nameKind} ${
        name}. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.`);
  }
}

屬性name第一個參數不能是@

this.renderer.setProperty(a,'type','button') // 修改input的type類型

setValue

setValue(node: any, value: string): void {
    node.nodeValue = value;
  }
let a = document.querySelector('#bbb');
    a.childNodes[0].nodeValue='bbb'

nodeValue 文本節點

childNodes 子節點合集

nodeName 節點名稱 大寫的 DIV或者其餘標籤

nodeType 節點類型

  • 元素節點 1
  • 屬性節點 2
  • 文本節點 3
  • 註釋節點 8

案例

<div id="bbb">
  dddd
  </div>	
要有文本節點才能添加
  let a = document.querySelector('#bbb');
  this.renderer.setValue( a.childNodes[0],'eeee')

listen

用法

let a = document.querySelector('#bbb');
    this.renderer.listen(a,'click',e=>{
      console.log(e);
    })
相關文章
相關標籤/搜索