摘要:为了能够支持跨平台,通过抽象层封装了不同平台的差异。这样我们就引出抽象类来对元素进行设置样式属性插入子元素等操作。
在《Angular开发实践(六):服务端渲染》这篇文章的最后,我们也提到了在服务端渲染中需要牢记的几件事件,其中就包括不要使用window、 document、 navigator等浏览器特有的类型以及直接操作DOM元素。
这样就引出了 Angular 主要特性之一:横跨所有平台。通过合适的方法,使用 Angular 构建的应用,可复用在多种不同平台的应用上 —— Web、移动 Web、移动应用、原生应用和桌面原生应用。
为了能够支持跨平台,Angular 通过抽象层封装了不同平台的差异。比如定义了抽象类 Renderer2 、抽象类 RootRenderer 等。此外还定义了以下引用类型:ElementRef、TemplateRef、ViewRef 、ComponentRef 和 ViewContainerRef 等。通过 模板变量、@ViewChild 等方法获取DOM元素。
为了演示,先定义一个组件DemoComponent:
import { AfterViewInit, Component, ElementRef, Renderer2, ViewChild } from "@angular/core"; @Component({ template: `获取组件中的divthis is DIV!DIV的id:{{demoDiv.id}} ` }) export class DemoComponent implements AfterViewInit { @ViewChild("demoDiv") demoDiv: ElementRef; // @ViewChild通过模板变量名获取 constructor(private renderer: Renderer2) { } ngAfterViewInit() { console.log("DIV的id:" + this.demoDiv.nativeElement.id); // DIV的id:demoDiv this.renderer.setStyle(this.demoDiv.nativeElement, "background-color", "red"); // 通过Renderer2设置div的css样式background-color } }
在Angular应用中不应该通过原生 API 或者 jQuery 来直接获取DOM元素:
let element1 = document.getElementById("demoDiv"); // jQuery获取: $("#demoDiv")
而是应该通过Angular提供的方法来获取DOM元素:
模板变量this is DIV!DIV的id:{{demoDiv.id}}
在组件模板中,我们在 div 上定义了 #demoDiv 的模板变量,那么 demoDiv 就等于该 div 的 DOM 对象,因此我们可以通过 demoDiv.id 直接获取 div 的 id。
@ViewChild@ViewChild("demoDiv") demoDiv: ElementRef; // @ViewChild通过模板变量名获取 ngAfterViewInit() { console.log("DIV的id:" + this.demoDiv.nativeElement.id); // DIV的id:demoDiv }
在组件类中,我们通过 @ViewChild 获取到包装有 div 的 DOM 对象的 ElementRef 对象,ElementRef 定义如下:
class ElementRef{ constructor(nativeElement: T) nativeElement: T }
因此我们可以在 ngAfterViewInit 中通过 this.demoDiv.nativeElement 获取到该 div 的 DOM 对象,然后获取元素的id。
操作组件中的div在上面通过几种方式获取到 div 的 DOM 对象,那么我们要如果对它进行操作呢(设置样式、属性、插入子元素等)?通过原始API 或者 jQuery 肯定是不允许的了。
这样我们就引出Angular抽象类 Renderer2 来对元素进行设置样式、属性、插入子元素等操作。
Renderer2 的定义如下:
class Renderer2 { get data: {...} destroyNode: ((node: any) => void) | null destroy(): void createElement(name: string, namespace?: string | null): any // 创建元素 createComment(value: string): any // 创建注释元素 createText(value: string): any // 创建文本元素 appendChild(parent: any, newChild: any): void // 添加子元素(在最后) insertBefore(parent: any, newChild: any, refChild: any): void // 添加子元素(在最前) removeChild(parent: any, oldChild: any): void // 移除子元素 selectRootElement(selectorOrNode: string | any): any // 获取根元素 parentNode(node: any): any // 获取父元素 nextSibling(node: any): any // 获取下一个兄弟元素 setAttribute(el: any, name: string, value: string, namespace?: string | null): void // 设置属性 removeAttribute(el: any, name: string, namespace?: string | null): void // 移除属性 addClass(el: any, name: string): void // 添加样式类 removeClass(el: any, name: string): void // 移除样式类 setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2): void // 设置样式 removeStyle(el: any, style: string, flags?: RendererStyleFlags2): void // 移除样式 setProperty(el: any, name: string, value: any): void // 设置DOM对象属性,不同于元素属性 setValue(node: any, value: string): void // 设置元素值 listen(target: "window" | "document" | "body" | any, eventName: string, callback: (event: any) => boolean | void): () => void // 注册事件 }
因此,我们想改变 div 的背景色,就可以这样做:
ngAfterViewInit() { this.renderer.setStyle(this.demoDiv.nativeElement, "background-color", "red"); // 通过Renderer2设置div的css样式background-color }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/93890.html
摘要:注更新元素节点和文本节点都提到了渲染器,这也是一个重要的概念。每一个视图对象都有一个属性,即是的引用,也就是组件渲染器,的实际更新操作由它完成。 原文链接:The mechanics of DOM updates in Angular showImg(https://segmentfault.com/img/remote/1460000014687960?w=419&h=268); ...
摘要:模块库开发实例随着前端框架的诞生,也会随之出现一些组件库,方便日常业务开发。在浏览器中,渲染是将模型映射到视图的过程。然而视图可以是页面中的段落表单按钮等其他元素,这些页面元素内部使用来表示。 angular模块库开发实例 随着前端框架的诞生,也会随之出现一些组件库,方便日常业务开发。今天就聊聊angular4组件库开发流程。 下图是button组件的基础文件。 showImg(htt...
摘要:在服务端渲染方面提供一套前后端同构解决方案,它就是统一平台,一项在服务端运行应用的技术。这些着陆页是纯,并且即使被禁用了也能显示。它会把客户端请求转换成服务端渲染的页面。它是服务端渲染器和你的应用之间的桥梁。 Angular Universal Angular在服务端渲染方面提供一套前后端同构解决方案,它就是 Angular Universal(统一平台),一项在服务端运行 Angul...
摘要:解决办法很简单,既然无法注入就不注入。可以利用工厂类代替直接注入的方式。示例代码如下利用对象去操作元素即可 这个错误一般是在构造函数中 注入 Renderer2 引起的。 解决办法很简单,既然无法注入Renderer2就不注入。可以利用工厂类RendererFactory2 代替直接注入Renderer2的方式。示例代码如下: import { Renderer2, RendererF...
摘要:前端每周清单第期微服务实践,与,组件技巧,攻防作者王下邀月熊编辑徐川前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点分为新闻热点开发教程工程实践深度阅读开源项目巅峰人生等栏目。 前端每周清单第 26 期:Node.js 微服务实践,Vue.js 与 GraphQL,Angular 组件技巧,HeadlessChrome 攻防 作者:王下邀月熊 编辑:徐川...
阅读 1240·2021-11-19 09:40
阅读 3055·2021-11-02 14:47
阅读 2974·2021-10-11 10:58
阅读 3197·2019-08-30 15:54
阅读 2641·2019-08-30 12:50
阅读 1709·2019-08-29 16:54
阅读 436·2019-08-29 15:38
阅读 1210·2019-08-29 15:19