在AngularJS 1.5中使用ES6类进行服务

时间:2017-05-03 13:28:52

标签: angularjs angular-services es6-class

我试图重构一些AngularJS 1.5服务代码以利用类。

我的服务定义如下:

(() => {
    "use strict";

    class notification {
        constructor($mdToast, $mdDialog, $state) {

            /* injected members */
            this.toast = $mdToast
            this.dialog = $mdDialog
            this.state = $state

            /* properties */
            this.transitioning = false
            this.working = false
        }

        openHelp() {
            this.showAlert({
                "title": "Help",
                "textContent": `Help is on the way!`,
                "ok": "OK"
            })
        }
        showAlert(options) {
            if (angular.isString(options)) {
                var text = angular.copy(options)
                options = {}
                options.textContent = text
                options.title = " "
            }
            if (!options.ok) {
                options.ok = "OK"
            }
            if (!options.clickOutsideToClose) {
                options.clickOutsideToClose = true
            }
            if (!options.ariaLabel) {
                options.ariaLabel = 'Alert'
            }
            if (!options.title) {
                options.title = "Alert"
            }
            return this.dialog.show(this.dialog.alert(options))
        }
        showConfirm(options) {
            if (angular.isString(options)) {
                var text = angular.copy(options)
                options = {}
                options.textContent = text
                options.title = " "
            }
            if (!options.ok) {
                options.ok = "OK"
            }
            if (!options.cancel) {
                options.cancel = "Cancel"
            }
            if (!options.clickOutsideToClose) {
                options.clickOutsideToClose = false
            }
            if (!options.ariaLabel) {
                options.ariaLabel = 'Confirm'
            }
            if (!options.title) {
                options.title = "Confirm"
            }
            return this.dialog.show(this.dialog.confirm(options))
        }
        showToast(toastMessage, position) {
            if (!position) { position = 'top' }
            return this.toast.show(this.toast.simple()
                .content(toastMessage)
                .position(position)
                .action('OK'))
        }
        showYesNo(options) {
            options.ok = "Yes"
            options.cancel = "No"
            return this.showConfirm(options)
        }
        uc() {
            return this.showAlert({
                htmlContent: "<img src='img\\underconstruction.jpg'>",
                ok: "OK",
                title: "Under Construction"
            })
        }

    }
    angular.module('NOTIFICATION', []).service("notification", notification)
})()

该服务似乎创建得很好,但是,当我从组件的控制器中引用它时,它已被注入到服务方法内部“this”引用服务已注入的控制器而不是服务。在查看调试器中的控制器时,似乎我为服务定义的所有方法实际上都已添加到控制器中。

在控制器中,我基本上将一些控制器方法映射到服务的方法,如下所示:

function $onInit() {
        Object.assign(ctrl, {
            // Properties        
            title: "FTP Order Processing",
            menuComponent: "appMenu",
            reportsOn: false,
            userName: "",
            notification: notification,
            // working: false,
            // Methods
            closeSideNav: closeSideNav,
            menuHit: menuHit,
            openHelp: notification.openHelp,
            showConfirm: notification.showConfirm,
            showSideNav: showSideNav,
            showAlert: notification.showAlert,
            showToast: notification.showToast,
            showYesNo: notification.showYesNo,
            toggleReports: toggleReports,
            // uc: uc
        })

        Object.defineProperty(ctrl, "working", {
            get: () => { return ctrl.notification.working },
            set: (value) => { ctrl.notification.working = value }
        })
    }

因此,“this”指的是控制器。当我使用非基于类的服务时,它无关紧要,因为我使用引用该服务的变量引用了服务中的服务成员。

所以我想我的问题是,当这些方法映射到另一个对象时,如何从其方法中引用服务类的成员?

2 个答案:

答案 0 :(得分:1)

这是我们为我们的类做的事情,ES6使用Angular 1.5 +:

import { decorator } from 'app/decorators';
export default class FooClass {
  /* @ngInject */
  constructor(Restangular) {
    this._Restangular = Restangular;
  }

  @decorator
  someMethod(argument_one) {
    return argument_one.property;
  }
}

所以它和你的一样,略有不同。为了以防万一,我留下了一个装饰器示例。

答案 1 :(得分:1)

这个问题与ES6类没有关系(它们只是ES5构造函数的语法糖),而是与JS有关。

将方法分配给其他对象时,如

foo.baz = bar.baz

foo.baz()foo作为this - 除非bar.baz被绑定为bar.baz = bar.baz.bind(baz),或者是具有bar的ES6箭头功能作为词汇this

将控制方法分配给控制器,这种方法不会很好,并且会导致错误的上下文。

这可以像

一样修复
Object.assign(this, {
  ...
  showAlert: notification.showAlert.bind(notification)
});

Object.assign(this, {
  ...
  showAlert: (...args) => notification.showAlert(...args)
});

但好的方法是不要让服务方法失去他们的背景。

控制器应该只将服务实例分配为

this.notification = notification;

并访问控制器中的this.notification.openHelp()或视图中的{{ $ctrl.notification.openHelp() }}等方法。

否则最好使用类原型方法:

showAlert(options) {
  return this.notification.showAlert(options);
}

由于它暴露了控制器原型上的方法,因此允许使用对于实例方法不可用的继承和测试方法(当控制器多次实例化时也更有效)。