angular11源码探索二[Renderer2]

其实我通过这段时间的深入学习,已经写到第6,7篇的,每天晚上都熬夜很晚,我发现了angular的宝贵东西,也慢慢明白了这个好东西,由于第一篇个人写的质量比较高,后面写的质量不高,感觉有点初级,一直没发,自己也开始迷茫了,研究源码的目标是为了什么,啃源码是一个很迷茫很打击自信有挑战性的东西,需要要一堆迷迷糊糊的东西去理解本质,加上前面几个月没怎么深入angular导致很多东西也忘记了,自己也是抱着一个初学者的态度去探究源码,已经编写的质量一直达不到自己的要求,但是我编写的一些东西,都是抱着初学者的态度去理解的,对于解决问题和从实际问题去理解angular还是有很大帮助的

技术成长分为三个阶段:

第一阶段:化难为易

第二阶段:由易变难

第三阶段:分割难易

自己的编写的时候是不是应该先做个第一阶段的事,理解怎么能全面的去,精通这个api,官网上面的介绍,说实例有点浅,自己能不能做到,遇到这个api基本能理解全部的方法,相信自己能编写20篇过后的质量可能有明显的提高,所以急不来,慢慢来,别过于抱着目的性去弄,有时候遇到太难的问题,容易导致心态崩溃,可以跟以前一样,从源码的基础上去啃透这个api,希望未来的自己能变得更强,学东西还是尽量让自己变得更加自信...

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(父节点,删除的子节点,)

删除所有子节点

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.ts

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);
    })
posted @ 2020-12-08 23:49  猫神甜辣酱  阅读(613)  评论(0编辑  收藏  举报