带有Typescript的Angular2,如何在延迟加载模块中使用Plupload CDN脚本文件?
Angular2 with Typescript, how to use Plupload CDN script file in lazy-loaded module?
我想在 Angular2 组件中使用 Plupload,并从 CDN 访问 Plupload JavaScript 文件。我希望它特定于一个组件,以便在不需要时不会下载它 - 我希望它位于延迟加载的模块中。我怎样才能做到这一点?
现在已在此页面上完整回答!
这个任务的结果如下:
- 将 Plupload 与 Angular 2 和 TypeScript
结合使用的示例
- 如何在 Angular 2
中从 CDN 延迟加载脚本
- 如何在惰性加载模块中使用 Plupload 的示例
如何在Angular2
中使用延迟加载的脚本
(查看编辑历史,了解曾经构成此问题的丑陋细节。)
在这种方法中不需要任何额外的加载器模块。
查看示例(检查 Woohoo 的控制台):http://plnkr.co/edit/gfUs4Uhe8kMGzPxwpBay?p=preview
更新了 plunker:https://plnkr.co/edit/leG062tg7uX8sLrA0i2i?p=preview
您可以通过将脚本 url 添加到您的文档来延迟加载一些 js:
创建 my-lazy-load.function.ts
:
export function lazyload(url) {
// based on https://friendlybit.com/js/lazy-loading-asyncronous-javascript/
let scripts = document.getElementsByTagName('script');
for (let i = scripts.length; i--;) {
if (scripts[i].src.match(url)) return true;
}
let s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = url;
let x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
return true;
}
在您要添加 plupload 的组件中:
import {lazyload} from "./my-lazy-load.function.ts";
export class MyComponent implements OnInit {
pluploadInterval:number = null;
hasPlupload: boolean = false;
ngOnInit() {
lazyload("https://cdnjs.cloudflare.com/ajax/libs/plupload/2.3.1/plupload.full.min.js");
this.pluploadInterval = window.setInterval(()=>{
if(window.plupload) { // you can check existence of plupload object any way you want
// Woohoo, I am ready to be used
this.hasPlupload = true; // everything is run outside ngZone, wrap it if angular2 is not reacting to changes, or change window.setInterval to setInterval
window.clearInterval(this.pluploadInterval); // don't forget to clean interval
}
}, 100); // timeinterval can vary
....
浏览器会自动加载。
注意if(plupload)
它假定脚本添加了全局对象plupload(我不知道它是否真的添加了,检查你的工作示例在纯javascript)。因为它是 jquery 扩展,你可以像这样检查它的原型:jQuery test for whether an object has a method?
旧历史:
@Reid 这里是 plunker:https://plnkr.co/edit/zDWWQbTQUSHBqCsrUMUi?p=preview plupload 实际上已加载,但添加到需要 define("plupload", ['./moxie'], extract);
我现在不确定如何从那里提取以及 require 属于哪个包......寻找正确模块加载器的代码属于plupload本身,这里是(来自plupload.dev.js):
if (typeof define === "function" && define.amd) {
define("plupload", ['./moxie'], extract);
} else if (typeof module === "object" && module.exports) {
module.exports = extract(require('./moxie'));
} else {
global.plupload = extract(global.moxie);
}
我认为最好的办法是使用 Require.js 库,这样您就可以从组件中动态加载脚本。
小的权衡是您必须将这个 18KB 的库添加到您的 index.html 页面 (CDN),但是如果您的第 3 方库很大,这可以为您节省大量的加载。
我没有使用 plupload 的经验,所以我将以下 plunkr 放在一起,它使用从 CDN 绘制的外部动画库。 plunkr 为 0 - 100 之间的数字设置动画。
https://plnkr.co/edit/fJCtezsERYHOYplLh7Jo?p=preview
index.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.3/require.min.js"></script>
component.ts
ngOnInit(){
// Dynamically loads the framework from the CDN.
require(["https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenLite.min.js"],
// This function is then called ONCE LOAD IS COMPLETE
function (common) {
// Do greensock things
var demo = {score:0},
scoreDisplay = document.getElementById("scoreDisplay");
//create a tween that changes the value of the score property of the demo object from 0 to 100 over the course of 20 seconds.
var tween = TweenLite.to(demo, 20, {score:100, onUpdate:showScore})
//each time the tween updates this function will be called.
function showScore() {
scoreDisplay.innerHTML = demo.score.toFixed(2);
}
});
}
我喜欢这种方法的一点是,在 require
的 onLoad 回调中,语法与库的正常实现没有变化,因此您只需将当前工作的代码复制粘贴到回调中即可.
以下是从 CDN 加载 Plupload 时创建延迟加载 Plupload 功能所需执行的操作的概述:
- 当需要该功能时(例如用户单击按钮或访问页面),动态添加一个
<script>
标签到页面以从 CDN 加载 Plupload 库。
- 等到库加载后再继续(否则您可能会收到
"plupload is undefined"
错误)。
- 显示 UI 以在您的 Angular 模板之一中与 Plupload 交互。在最简单的形式中,这个 UI 由两个按钮组成:"Select files" 和 "Upload files"。
- 初始化 Plupload 并将其连接到 UI。
完整的工作代码:https://plnkr.co/edit/4t39Rod4YNAOrHmZdxqc?p=preview
我的实现中请注意以下几点:
- 关于#2。检查 Plupload 是否已完成加载的更好方法是轮询全局名称空间以查找
plupload
变量是否存在。只要 window.plupload
不存在,就意味着库还没有加载,我们不应该继续。为简单起见,我的代码只等待一秒钟然后继续。
- 数字 4 可能有点棘手。 Plupload 大量使用直接 DOM 访问将其 API 连接到 HTML(例如
document.getElementById('filelist')
)。这是 Angular 不鼓励的事情,您应该尽可能避免。更具体的直接DOM访问用在以下地方:
- 告诉 Plupload 哪个 DOM 元素应该触发 "Select files" 对话框 (他们称之为
browse_button
配置选项)。为此,我无法避免直接 DOM 引用,我使用 @ViewChild
装饰器来获取 "Select Files" 按钮。
- 在模板中显示选定的文件。 为此,我将 Plupload 语法转换为常规 Angular 语法。我将选定的文件推送到名为
fileList
的 class 属性,我使用标准 *ngFor
. 在模板中显示该文件
- "Upload Files" 按钮会触发一些执行实际上传的代码,并刷新 UI 以显示上传进度。再一次,我使用事件绑定和数据绑定将其转换为常规 Angular 语法。
如果您有任何问题,请告诉我。
我想在 Angular2 组件中使用 Plupload,并从 CDN 访问 Plupload JavaScript 文件。我希望它特定于一个组件,以便在不需要时不会下载它 - 我希望它位于延迟加载的模块中。我怎样才能做到这一点?
现在已在此页面上完整回答!
这个任务的结果如下:
- 将 Plupload 与 Angular 2 和 TypeScript 结合使用的示例
- 如何在 Angular 2 中从 CDN 延迟加载脚本
- 如何在惰性加载模块中使用 Plupload 的示例
如何在Angular2
中使用延迟加载的脚本(查看编辑历史,了解曾经构成此问题的丑陋细节。)
在这种方法中不需要任何额外的加载器模块。
查看示例(检查 Woohoo 的控制台):http://plnkr.co/edit/gfUs4Uhe8kMGzPxwpBay?p=preview 更新了 plunker:https://plnkr.co/edit/leG062tg7uX8sLrA0i2i?p=preview
您可以通过将脚本 url 添加到您的文档来延迟加载一些 js:
创建 my-lazy-load.function.ts
:
export function lazyload(url) {
// based on https://friendlybit.com/js/lazy-loading-asyncronous-javascript/
let scripts = document.getElementsByTagName('script');
for (let i = scripts.length; i--;) {
if (scripts[i].src.match(url)) return true;
}
let s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = url;
let x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
return true;
}
在您要添加 plupload 的组件中:
import {lazyload} from "./my-lazy-load.function.ts";
export class MyComponent implements OnInit {
pluploadInterval:number = null;
hasPlupload: boolean = false;
ngOnInit() {
lazyload("https://cdnjs.cloudflare.com/ajax/libs/plupload/2.3.1/plupload.full.min.js");
this.pluploadInterval = window.setInterval(()=>{
if(window.plupload) { // you can check existence of plupload object any way you want
// Woohoo, I am ready to be used
this.hasPlupload = true; // everything is run outside ngZone, wrap it if angular2 is not reacting to changes, or change window.setInterval to setInterval
window.clearInterval(this.pluploadInterval); // don't forget to clean interval
}
}, 100); // timeinterval can vary
....
浏览器会自动加载。
注意if(plupload)
它假定脚本添加了全局对象plupload(我不知道它是否真的添加了,检查你的工作示例在纯javascript)。因为它是 jquery 扩展,你可以像这样检查它的原型:jQuery test for whether an object has a method?
旧历史:
@Reid 这里是 plunker:https://plnkr.co/edit/zDWWQbTQUSHBqCsrUMUi?p=preview plupload 实际上已加载,但添加到需要 define("plupload", ['./moxie'], extract);
我现在不确定如何从那里提取以及 require 属于哪个包......寻找正确模块加载器的代码属于plupload本身,这里是(来自plupload.dev.js):
if (typeof define === "function" && define.amd) {
define("plupload", ['./moxie'], extract);
} else if (typeof module === "object" && module.exports) {
module.exports = extract(require('./moxie'));
} else {
global.plupload = extract(global.moxie);
}
我认为最好的办法是使用 Require.js 库,这样您就可以从组件中动态加载脚本。
小的权衡是您必须将这个 18KB 的库添加到您的 index.html 页面 (CDN),但是如果您的第 3 方库很大,这可以为您节省大量的加载。
我没有使用 plupload 的经验,所以我将以下 plunkr 放在一起,它使用从 CDN 绘制的外部动画库。 plunkr 为 0 - 100 之间的数字设置动画。
https://plnkr.co/edit/fJCtezsERYHOYplLh7Jo?p=preview
index.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.3/require.min.js"></script>
component.ts
ngOnInit(){
// Dynamically loads the framework from the CDN.
require(["https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenLite.min.js"],
// This function is then called ONCE LOAD IS COMPLETE
function (common) {
// Do greensock things
var demo = {score:0},
scoreDisplay = document.getElementById("scoreDisplay");
//create a tween that changes the value of the score property of the demo object from 0 to 100 over the course of 20 seconds.
var tween = TweenLite.to(demo, 20, {score:100, onUpdate:showScore})
//each time the tween updates this function will be called.
function showScore() {
scoreDisplay.innerHTML = demo.score.toFixed(2);
}
});
}
我喜欢这种方法的一点是,在 require
的 onLoad 回调中,语法与库的正常实现没有变化,因此您只需将当前工作的代码复制粘贴到回调中即可.
以下是从 CDN 加载 Plupload 时创建延迟加载 Plupload 功能所需执行的操作的概述:
- 当需要该功能时(例如用户单击按钮或访问页面),动态添加一个
<script>
标签到页面以从 CDN 加载 Plupload 库。 - 等到库加载后再继续(否则您可能会收到
"plupload is undefined"
错误)。 - 显示 UI 以在您的 Angular 模板之一中与 Plupload 交互。在最简单的形式中,这个 UI 由两个按钮组成:"Select files" 和 "Upload files"。
- 初始化 Plupload 并将其连接到 UI。
完整的工作代码:https://plnkr.co/edit/4t39Rod4YNAOrHmZdxqc?p=preview
我的实现中请注意以下几点:
- 关于#2。检查 Plupload 是否已完成加载的更好方法是轮询全局名称空间以查找
plupload
变量是否存在。只要window.plupload
不存在,就意味着库还没有加载,我们不应该继续。为简单起见,我的代码只等待一秒钟然后继续。 - 数字 4 可能有点棘手。 Plupload 大量使用直接 DOM 访问将其 API 连接到 HTML(例如
document.getElementById('filelist')
)。这是 Angular 不鼓励的事情,您应该尽可能避免。更具体的直接DOM访问用在以下地方:- 告诉 Plupload 哪个 DOM 元素应该触发 "Select files" 对话框 (他们称之为
browse_button
配置选项)。为此,我无法避免直接 DOM 引用,我使用@ViewChild
装饰器来获取 "Select Files" 按钮。 - 在模板中显示选定的文件。 为此,我将 Plupload 语法转换为常规 Angular 语法。我将选定的文件推送到名为
fileList
的 class 属性,我使用标准*ngFor
. 在模板中显示该文件
- "Upload Files" 按钮会触发一些执行实际上传的代码,并刷新 UI 以显示上传进度。再一次,我使用事件绑定和数据绑定将其转换为常规 Angular 语法。
- 告诉 Plupload 哪个 DOM 元素应该触发 "Select files" 对话框 (他们称之为
如果您有任何问题,请告诉我。