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 相关文章推荐
浅谈 javascript 事件处理
Jan 04 Javascript
深入浅析JavaScript中的scrollTop
Jul 11 Javascript
JavaScript实战之带收放动画效果的导航菜单
Aug 16 Javascript
Jquery AJAX POST与GET之间的区别详细介绍
Oct 17 Javascript
AngularJS指令用法详解
Nov 02 Javascript
微信小程序 require机制详解及实例代码
Dec 14 Javascript
js实现简单的手风琴效果
Feb 27 Javascript
Vue二次封装axios为插件使用详解
May 21 Javascript
Angular ElementRef简介及其使用
Oct 01 Javascript
如何优雅的在一台vps(云主机)上面部署vue+mongodb+express项目
Jan 20 Javascript
vue实现购物车抛物线小球动画效果的方法详解
Feb 13 Javascript
vue实现图片懒加载的方法分析
Feb 05 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
PHP的面向对象编程
2006/10/09 PHP
symfony表单与页面实现技巧
2015/01/26 PHP
php读取csc文件并输出
2015/05/21 PHP
php实现与python进行socket通信的方法示例
2017/08/30 PHP
PHP与Web页面交互操作实例分析
2020/06/02 PHP
7个有用的jQuery代码片段分享
2015/05/19 Javascript
js判断手机端(Android手机还是iPhone手机)
2015/07/22 Javascript
jquery彩色投票进度条简单实例演示
2020/07/23 Javascript
JQuery点击行tr实现checkBox选中的简单实例
2016/05/26 Javascript
JS简单获取当前年月日星期的方法示例
2017/02/07 Javascript
Vue 2.0学习笔记之Vue中的computed属性
2017/10/16 Javascript
使用vue-cli编写vue插件的方法
2018/02/26 Javascript
JavaScript实现的DOM绘制柱状图效果示例
2018/08/08 Javascript
JavaScript实现简单的隐藏式侧边栏功能示例
2018/08/31 Javascript
vue打包相关细节整理(小结)
2018/09/28 Javascript
Vuejs监听vuex中值的变化的方法示例
2018/12/02 Javascript
点击按钮弹出模态框的一系列操作代码实例
2019/03/29 Javascript
优雅的处理vue项目异常实战记录
2019/06/05 Javascript
[01:29]Ti4循环赛第三日精彩回顾
2014/07/13 DOTA
[00:50]深扒TI7聊天轮盘语音出处6
2017/05/11 DOTA
python字符串替换的2种方法
2014/11/30 Python
使用Python的Tornado框架实现一个简单的WebQQ机器人
2015/04/24 Python
python实现类的静态变量用法实例
2015/05/08 Python
python使用turtle绘制分形树
2018/06/22 Python
python单线程文件传输的实例(C/S)
2019/02/13 Python
Python 类方法和实例方法(@classmethod),静态方法(@staticmethod)原理与用法分析
2019/09/20 Python
Python os模块常用方法和属性总结
2020/02/20 Python
CSS3近阶段篇之酷炫的3D旋转透视
2016/04/28 HTML / CSS
英国汽车座椅和婴儿车购物网站:Uber Kids
2017/04/19 全球购物
入职担保书怎么写
2014/05/12 职场文书
群众路线个人自我剖析材料
2014/10/07 职场文书
2014幼儿园大班工作总结
2014/11/10 职场文书
会议通知
2015/04/15 职场文书
2015小学教师年度考核工作总结
2015/05/12 职场文书
Oracle 区块链表创建过程详解
2021/05/15 Oracle
MySQL 分区表中分区键为什么必须是主键的一部分
2022/03/17 MySQL