Angular 4 TypeScript callaback with this. in block



我有一个主题,我正在将其转换为 Angular 4 管理面板。该主题有一个名为 app 的文件.js其中包含一个我正在尝试转换为我的layout.component.ts在应用程序中.js有几个代码块尝试访问类外的函数,但我已将所有函数转换为我layout.component.ts的方法;

$(window).resize(function(){
this.resizePageContent();
});

运行此程序会产生 Javascript 错误。但是,在这种情况下,我的layout.component.ts上应该使用一种方法。

this.resizePageContent is not a function

所以我想知道哪种是转换它的最佳方式,以便调用layout.component.ts方法。这是我尝试过的,但我不确定这是否是最好的方法以及为什么它有效。

$(window).resize(()=>{
this.resizePageContent();
});

用上面的代码替换它后,错误消失了。

这是应用程序的预览.js 它有 700 多行代码,所以我无法将其全部粘贴到此处;

更新:

var App = function() {
/* Helper variables - set in uiInit() */
var page, pageContent, header, footer, sidebar, sScroll, sidebarAlt, sScrollAlt;
/* Initialization UI Code */
var uiInit = function() {...};
/* Page Loading functionality */
var pageLoading = function(){..};
/* Gets window width cross browser */
var getWindowWidth = function(){...};
/* Sidebar Navigation functionality */
var handleNav = function() {..};
/* Scrolls the page (static layout) or the sidebar scroll element (fixed header/sidebars layout) to a specific position - Used when a submenu opens */
var handlePageScroll = function(sElem, sHeightDiff, sSpeed) {...};
/* Sidebar Functionality */
var handleSidebar = function(mode, extra) {...};
/* Resize #page-content to fill empty space if exists */
var resizePageContent = function() {...};
/* Interactive blocks functionality */
var interactiveBlocks = function() {...};
/* Scroll to top functionality */
var scrollToTop = function() {...};
/* Demo chat functionality (in sidebar) */
var chatUi = function() {...};
/* Template Options, change features functionality */
var templateOptions = function() {...};
/* Datatables basic Bootstrap integration (pagination integration included under the Datatables plugin in plugins.js) */
var dtIntegration = function() {...};
/* Print functionality - Hides all sidebars, prints the page and then restores them (To fix an issue with CSS print styles in webkit browsers)  */
var handlePrint = function() {...};
return {
init: function() {
uiInit(); // Initialize UI Code
pageLoading(); // Initialize Page Loading
},
sidebar: function(mode, extra) {
handleSidebar(mode, extra); // Handle sidebars - access functionality from everywhere
},
datatables: function() {
dtIntegration(); // Datatables Bootstrap integration
},
pagePrint: function() {
handlePrint(); // Print functionality
}
};
}();
/* Initialize app when page loads */
$(function(){ App.init(); });

这是我的layout.component.ts;

import { Component, OnInit } from '@angular/core';
declare var jQuery: any;
declare var $: any;
declare var window: any;
declare var document: any;
declare  var Cookies: any;
@Component({
selector: 'app-layout',
templateUrl: './layout.component.html',
styleUrls: ['./layout.component.css']
})
export class LayoutComponent implements OnInit {
public page;
public pageContent;
public header;
public footer;
public sidebar;
public sScroll;
public sidebarAlt;
public sScrollAlt;
constructor() { }
ngOnInit() {
this.init();
}
uiInit (): void {...}
pageLoading (): void {...}
getWindowWidth (): any {...}
handleNav (): any {...}
handlePageScroll (sElem, sHeightDiff, sSpeed): void {...}
handleSidebar (mode, extra?:any): any {
if (mode === 'init') {
// Init sidebars scrolling functionality
this.handleSidebar('sidebar-scroll');
this.handleSidebar('sidebar-alt-scroll');
// Close the other sidebar if we hover over a partial one
// In smaller screens (the same applies to resized browsers) two visible sidebars
// could mess up our main content (not enough space), so we hide the other one :-)
$('.sidebar-partial #sidebar')
.mouseenter(function(){ this.handleSidebar('close-sidebar-alt'); });
$('.sidebar-alt-partial #sidebar-alt')
.mouseenter(function(){ this.handleSidebar('close-sidebar'); });
} else {
var windowW = this.getWindowWidth();
if (mode === 'toggle-sidebar') {
if ( windowW > 991) { // Toggle main sidebar in large screens (> 991px)
this.page.toggleClass('sidebar-visible-lg');
if (this.page.hasClass('sidebar-mini')) {
this.page.toggleClass('sidebar-visible-lg-mini');
}
if (this.page.hasClass('sidebar-visible-lg')) {
this.handleSidebar('close-sidebar-alt');
}
// If 'toggle-other' is set, open the alternative sidebar when we close this one
if (extra === 'toggle-other') {
if (!this.page.hasClass('sidebar-visible-lg')) {
this.handleSidebar('open-sidebar-alt');
}
}
} else { // Toggle main sidebar in small screens (< 992px)
this.page.toggleClass('sidebar-visible-xs');
if (this.page.hasClass('sidebar-visible-xs')) {
this.handleSidebar('close-sidebar-alt');
}
}
// Handle main sidebar scrolling functionality
this.handleSidebar('sidebar-scroll');
}
else if (mode === 'toggle-sidebar-alt') {
if ( windowW > 991) { // Toggle alternative sidebar in large screens (> 991px)
this.page.toggleClass('sidebar-alt-visible-lg');
if (this.page.hasClass('sidebar-alt-visible-lg')) {
this.handleSidebar('close-sidebar');
}
// If 'toggle-other' is set open the main sidebar when we close the alternative
if (extra === 'toggle-other') {
if (!this.page.hasClass('sidebar-alt-visible-lg')) {
this.handleSidebar('open-sidebar');
}
}
} else { // Toggle alternative sidebar in small screens (< 992px)
this.page.toggleClass('sidebar-alt-visible-xs');
if (this.page.hasClass('sidebar-alt-visible-xs')) {
this.handleSidebar('close-sidebar');
}
}
}
else if (mode === 'open-sidebar') {
if ( windowW > 991) { // Open main sidebar in large screens (> 991px)
if (this.page.hasClass('sidebar-mini')) { this.page.removeClass('sidebar-visible-lg-mini'); }
this.page.addClass('sidebar-visible-lg');
} else { // Open main sidebar in small screens (< 992px)
this.page.addClass('sidebar-visible-xs');
}
// Close the other sidebar
this.handleSidebar('close-sidebar-alt');
}
else if (mode === 'open-sidebar-alt') {
if ( windowW > 991) { // Open alternative sidebar in large screens (> 991px)
this.page.addClass('sidebar-alt-visible-lg');
} else { // Open alternative sidebar in small screens (< 992px)
this.page.addClass('sidebar-alt-visible-xs');
}
// Close the other sidebar
this.handleSidebar('close-sidebar');
}
else if (mode === 'close-sidebar') {
if ( windowW > 991) { // Close main sidebar in large screens (> 991px)
this.page.removeClass('sidebar-visible-lg');
if (this.page.hasClass('sidebar-mini')) { this.page.addClass('sidebar-visible-lg-mini'); }
} else { // Close main sidebar in small screens (< 992px)
this.page.removeClass('sidebar-visible-xs');
}
}
else if (mode === 'close-sidebar-alt') {
if ( windowW > 991) { // Close alternative sidebar in large screens (> 991px)
this.page.removeClass('sidebar-alt-visible-lg');
} else { // Close alternative sidebar in small screens (< 992px)
this.page.removeClass('sidebar-alt-visible-xs');
}
}
else if (mode === 'sidebar-scroll') { // Handle main sidebar scrolling
if (this.page.hasClass('sidebar-mini') && this.page.hasClass('sidebar-visible-lg-mini') && (windowW > 991)) { // Destroy main sidebar scrolling when in mini sidebar mode
if (this.sScroll.length && this.sScroll.parent('.slimScrollDiv').length) {
this.sScroll
.slimScroll({destroy: true});
this.sScroll
.attr('style', '');
}
}
else if ((this.page.hasClass('header-fixed-top') || this.page.hasClass('header-fixed-bottom'))) {
var sHeight = $(window).height();
if (this.sScroll.length && (!this.sScroll.parent('.slimScrollDiv').length)) { // If scrolling does not exist init it..
this.sScroll
.slimScroll({
height: sHeight,
color: '#fff',
size: '3px',
touchScrollStep: 100
});
// Handle main sidebar's scrolling functionality on resize or orientation change
var sScrollTimeout;
$(window).on('resize orientationchange', function(){
clearTimeout(sScrollTimeout);
sScrollTimeout = setTimeout(function(){
this.handleSidebar('sidebar-scroll');
}, 150);
});
}
else { // ..else resize scrolling height
this.sScroll
.add(this.sScroll.parent())
.css('height', sHeight);
}
}
}
else if (mode === 'sidebar-alt-scroll') { // Init alternative sidebar scrolling
if ((this.page.hasClass('header-fixed-top') || this.page.hasClass('header-fixed-bottom'))) {
var sHeightAlt = $(window).height();
if (this.sScrollAlt.length && (!this.sScrollAlt.parent('.slimScrollDiv').length)) { // If scrolling does not exist init it..
this.sScrollAlt
.slimScroll({
height: sHeightAlt,
color: '#fff',
size: '3px',
touchScrollStep: 100
});
// Resize alternative sidebar scrolling height on window resize or orientation change
var sScrollAltTimeout;
$(window).on('resize orientationchange', function(){
clearTimeout(sScrollAltTimeout);
sScrollAltTimeout = setTimeout(function(){
this.handleSidebar('sidebar-alt-scroll');
}, 150);
});
}
else { // ..else resize scrolling height
this.sScrollAlt
.add(this.sScrollAlt.parent())
.css('height', sHeightAlt);
}
}
}
}
return false;
}
resizePageContent (): void {...}
interactiveBlocks (): void {...}
scrollToTop (): any{...}
chatUi (): any {...}
templateOptions (): void {...}
dtIntegration (): any {...}
handlePrint (): void {...}

//Methods from original object
init (): void {
this.uiInit(); // Initialize UI Code
this.pageLoading(); // Initialize Page Loading
}
//Originally sidebar
CallhandleSidebar(mode, extra): void {
this.handleSidebar(mode, extra); // Handle sidebars - access functionality from everywhere
}
datatables() :void {
this.dtIntegration(); // Datatables Bootstrap integration
}
pagePrint (): void {
this.handlePrint(); // Print functionality
}
}

您能否给我一个例子,说明 TypeScript 如何输出这样的东西;

$(window).resize(()=>{
this.resizePageContent();
});

。只是为了很好地了解它是如何工作的。

在您的情况下,使用代码

$(window).resize(()=>{
this.resizePageContent();
});

是访问回调函数范围之外的函数和变量的正确方法。

使用时

function() {
this.something;
}

"this"绑定到函数的作用域,而不是类的作用域。

使用时

() => {
this.something
}

即使用 ECMAScript 6 箭头表示法。Ecmascript 6 看到了词法 this 的引入,在后一种情况下,"this" 关键字指的是定义的类。

有关详细信息,请参阅 http://es6-features.org/#Lexicalthis 和 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_this 。

如果你只需要在回调中委托或一行编码器,那就去做这个:

$(window).resize(()=> this.resizePageContent());

或者您也可以使用以下方法来调整页面内容的大小:

另一个关于堆栈溢出的问题,以在 Angular 上下文中捕获窗口大小调整事件

并制作 resizePageContent(( 方法来侦听该事件。

基于意见的问题,但就个人而言,最好的方法是使用类字段 并分配一个箭头函数定义,并在使用角度时不使用jQuery:

window.addEventListener('resize', this.resizePageContent);

在你的类中,你应该像这样定义方法:

private resizePageContent: EventListener = (event: UIEvent): void => {
};

这样做的最大优点是可以删除事件侦听器,这在使用匿名箭头函数时是不可能的

普伦克尔

另一种选择是使用bind(this)来保留this上下文:

window.addEventListener('resize', this.resizePageContent.bind(this));

这样,您就不需要将回调分配给类的字段。但是使用bind会创建该方法的副本,这使得删除事件侦听器变得更加困难(并非不可能(。

您也可以使用@HostListener立即从组件中收听它。事件的删除是在内部通过组件销毁的角度来完成

@HostListener('window:resize', ['$event'])
public resizePageContent(event: Event) {}

您收到错误的原因是您使用了function关键字。这会将this上下文更改为定义为回调的匿名函数

最新更新