Angular6 用户自定义标签开发的实现方法


Posted in Javascript onJanuary 08, 2019

2018年4月23随着angular6 发布,我们可以看到在其官方手册中的模板元素章节中增加了一个Element 条目(中文),通过说明我们可以知道这个功能可以帮助我们将angular以html标签的形式嵌入到非angular的页面环境中。下面我们就通过一个简单的例子演示Angular6中的这一新功能。

新建angular工程

通过ng命令新建custom-tag工程

ng new custom-tag

cli新建完相应文件后会通过npm下载所信赖的包,完成后进入目录验证工作空间是否正常。

$cd custom-tag
$ng serve --open

--open参数的作用是直接打开浏览器,也可以通过浏览器中直接输入localhost:4200。

Angular6 用户自定义标签开发的实现方法

增加标签功能

修改app.component.html 内容

<!--The content below is only a placeholder and can be replaced.-->
<!--
<div style="text-align:center">
 <h1>
  Welcome to {{ title }}!
 </h1>
 <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<h2>Here are some links to help you start: </h2>
<ul>
 <li>
  <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial" rel="external nofollow" >Tour of Heroes</a></h2>
 </li>
 <li>
  <h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki" rel="external nofollow" >CLI Documentation</a></h2>
 </li>
 <li>
  <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/" rel="external nofollow" >Angular blog</a></h2>
 </li>
</ul>
-->
<input #inputtext type="text" placeholder="条目">
<input type="button" value="增加" (click)="addItem(inputtext.value)">
<ul>
  <li *ngFor="let item of items">{{item}}</li>
</ul>

为对应的类增加 addItem()方法,向类中的条目集合(items)增加用户输入的一个条目。

import { Component } from '@angular/core';

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 
 addItem(item:string){
  console.log(`${item} to be added!`);
  this.items.push(item); 
 }

 items:string[] =[];
}

小结

到目前为止这是一个普通的angular应用,通过增加按钮,要以向列表中增加元素。

Angular6 用户自定义标签开发的实现方法

应用状态

将完成内容转换为自定义标签

增加@angular/comonents信赖

$ng add @angular/elements

修改app.module.ts

从包中导入相关依赖:

import { Injector} from '@angular/core';
import { createCustomElement } from '@angular/elements';

将AppComponent改为动态组件,并通过createCustomElement()注册AppComponent为custom-items

import { BrowserModule } from '@angular/platform-browser';
import { NgModule,Injector } from '@angular/core';

import { createCustomElement } from '@angular/elements';

import { AppComponent } from './app.component';

@NgModule({
 declarations: [
  AppComponent
 ],
 imports: [
  BrowserModule
 ],
 providers: [],
 //bootstrap: [AppComponent]
 entryComponents : [
  AppComponent
 ]
})
export class AppModule {
 constructor(private injector : Injector){
  const cust_tag = createCustomElement(AppComponent, {injector : this.injector});
  customElements.define('custom-items',cust_tag);
 }

 ngDoBootstrap() {}
 }

修改index.html页面

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>CustomTag</title>
  <base href="/" rel="external nofollow" >

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico" rel="external nofollow" >
</head>

<body>
  <!--<app-root></app-root>-->
  <custom-items></custom-items>
</body>

</html>

页面重新出现在浏览器中了,功能也同先前一模一样。

由于浏览器版本的原因可能会出现下面错误,无法创建自定义标签

elements.js:384 Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
    at NgElementImpl.NgElement [as constructor] (elements.js:384)
    at new NgElementImpl (elements.js:420)
    at new AppModule (app.module.ts:24)
    at _createClass (core.js:8421)
    at _createProviderInstance (core.js:8393)
    at initNgModule (core.js:8326)
    at new NgModuleRef_ (core.js:9052)
    at createNgModuleRef (core.js:9041)
    at Object.debugCreateNgModuleRef [as createNgModuleRef] (core.js:10866)
    at NgModuleFactory_.push../node_modules/@angular/core/fesm5/core.js.NgModuleFactory_.create (core.js:11583)

可以通过修改tsconfig.json中的构建目标至es6解决该问题

{
 "compileOnSave": false,
 "compilerOptions": {
  "baseUrl": "./",
  "outDir": "./dist/out-tsc",
  "sourceMap": true,
  "declaration": false,
  "moduleResolution": "node",
  "emitDecoratorMetadata": true,
  "experimentalDecorators": true,
  "target": "es6",
  "typeRoots": [
   "node_modules/@types"
  ],
  "lib": [
   "es2017",
   "dom"
  ]
 }
}

增加外部事件

通过output 可以为自定义标签增加自定义事件

import { Component,Output, EventEmitter } from '@angular/core';

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 
 @Output() itemAdded:EventEmitter<string> = new EventEmitter<string>();
 addItem(item:string){
  console.log(`${item} to be added!`);
  this.items.push(item); 
  // 向外发送自定义事件
  this.itemAdded.emit(item);
 }

 items:string[] =[];
}

在客户端页面可以通过自定义标签对象的addEventListener()方法增加自定义事件响应,通过 event.detail可以获取到angular内部发送的内容

<script>
    var items = document.querySelector('custom-items');

    items.addEventListener('itemAdded', (event) => {
      console.log(event);
    })
  </script>

完结与发布

在package.json中增加发布脚本

"scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build --prod --output-hashing none",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },

通过npm run build 执行构建,由于我们关闭了文件名hash,得到的输出目录内容如下:

liunan@liunan-desktop:~/webDev/custom-tag$ ls ./dist/custom-tag/
3rdpartylicenses.txt favicon.ico index.html main.js polyfills.js runtime.js scripts.js styles.css

我们可以看到输出的index.html文件中采用如下方式引用了定义标签的输出,如果其他用户使用会非常不便,

<script type="text/javascript" src="runtime.js"></script>
<script type="text/javascript" src="polyfills.js"></script>
<script type="text/javascript" src="scripts.js"></script>
<script type="text/javascript" src="main.js"></script>

我们可以通过使用cat命令将这些文件按照上面顺序合并成一个文件

$cat runtime.js polyfills.js scripts.js main.js > custom-items.js

这样用户就可以引用单个文件来使用我们制做的custom-items了。

一定注记合并文件的次序,需要严格按照上述次序进行,否则脚本可能不能正常工作。

示例代码

在线示例

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQuery 学习笔记 选择器之六
Jul 23 Javascript
jqGrid日期格式的判断示例代码(开始日期与结束日期)
Nov 08 Javascript
node.js中的console.trace方法使用说明
Dec 09 Javascript
JavaScript实现梯形乘法表的方法
Apr 25 Javascript
解决jQuery上传插件Uploadify出现Http Error 302错误的方法
Dec 18 Javascript
JavaScript数据推送Comet技术详解
Apr 07 Javascript
深入浅出ES6新特性之函数默认参数和箭头函数
Aug 01 Javascript
详解VUE的状态控制与延时加载刷新
Mar 27 Javascript
jquery实现倒计时小应用
Sep 19 jQuery
jQuery EasyUI开发技巧总结
Sep 26 jQuery
vue+element实现表单校验功能
May 20 Javascript
nuxt+axios实现打包后动态修改请求地址的方法
Apr 22 Javascript
JS实现的获取银行卡号归属地及银行卡类型操作示例
Jan 08 #Javascript
关于微信小程序登录的那些事
Jan 08 #Javascript
Vue2.x Todo之自定义指令实现自动聚焦的方法
Jan 08 #Javascript
关于React动态加载路由处理的相关问题
Jan 07 #Javascript
vue+iview 兼容IE11浏览器的实现方法
Jan 07 #Javascript
详解Vue iview IE浏览器不兼容报错(Iview Bable polyfill)
Jan 07 #Javascript
利用React Router4实现的服务端直出渲染(SSR)
Jan 07 #Javascript
You might like
ip签名探针
2006/10/09 PHP
基于mysql的论坛(5)
2006/10/09 PHP
PHP无限分类的类
2007/01/02 PHP
php 高效率写法 推荐
2010/02/21 PHP
PHP使用Pear发送邮件(Windows环境)
2016/01/05 PHP
CakePHP框架Model关联对象用法分析
2017/08/04 PHP
改变javascript函数内部this指针指向的三种方法
2010/04/23 Javascript
多个datatable共存造成多个表格的checkbox都被选中
2013/07/11 Javascript
javascript制作的网页侧边弹出框思路及实现代码
2014/05/21 Javascript
让checkbox不选中即将选中的checkbox不选中
2014/07/11 Javascript
jQuery采用连缀写法实现的折叠菜单效果
2015/09/18 Javascript
解决VUE框架 导致绑定事件的阻止冒泡失效问题
2018/02/24 Javascript
Angular8路由守卫原理和使用方法
2019/08/29 Javascript
vue项目中使用bpmn为节点添加颜色的方法
2020/04/30 Javascript
在项目vue中使用echarts的操作步骤
2020/09/07 Javascript
Pyhthon中使用compileall模块编译源文件为pyc文件
2015/04/28 Python
Python语法快速入门指南
2015/10/12 Python
Python set常用操作函数集锦
2017/11/15 Python
Python实现霍夫圆和椭圆变换代码详解
2018/01/12 Python
Python实现上下班抢个顺风单脚本
2018/02/07 Python
基于numpy.random.randn()与rand()的区别详解
2018/04/17 Python
Python基于opencv实现的简单画板功能示例
2019/03/04 Python
Django REST Framework序列化外键获取外键的值方法
2019/07/26 Python
python程序中的线程操作 concurrent模块使用详解
2019/09/23 Python
如何使用python3获取当前路径及os.path.dirname的使用
2019/12/13 Python
python设置代理和添加镜像源的方法
2020/02/14 Python
tensorflow 大于某个值为1,小于为0的实例
2020/06/30 Python
python多线程semaphore实现线程数控制的示例
2020/08/10 Python
利用HTML5绘制点线面组成的3D图形的示例
2015/05/12 HTML / CSS
路易威登和香奈儿手袋:LuxeDH
2017/01/12 全球购物
Holiday Inn中国官网:IHG旗下假日酒店预订
2018/04/08 全球购物
美国最大的购物网站:Amazon.com(亚马逊美国)
2020/05/23 全球购物
医大实习自我鉴定
2013/12/07 职场文书
《散步》教学反思
2014/03/02 职场文书
廉洁自律心得体会2016
2016/01/13 职场文书
2016高校自主招生自荐信范文
2016/01/28 职场文书