npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

angular-utils

v0.2.7

Published

just angular1.x es6 utils

Downloads

56

Readme

angular-utils

Build Status npm version npm downloads coverage

注意: 0.2.x 版本的使用方式与之前 0.1.x 的使用方式有所不同

// 需要在 AngularJS 启动时候引入 ngUtils 模块
import ngUtils from 'angular-utils';
angular.module('app', [ngUtils]); 

使用 装饰器

关于AngularJS与装饰器

  • @Router

@Router 只记录路由配置(注意这里指的是 UI-Router ^0.2.18), 并未进行路由配置. 因此使用 decoratedModule 中的 routerAll 方法配置路由

注意: 如果使用 Uglify 压缩代码, 请禁用 mangle { mangle: false } 如果使用 UglifyJS2 压缩代码, 请保持函数名称 mangle: { keep_fnames: true }

import { Router } from 'angular-utils/decorators';
import { decoratedModule } from 'angular-utils/utils';
import ExampleTplUrl from './example.tpl.html';

@Router('example', {
    url: '/example',
    templateUrl: ExampleTplUrl,
    controller: 'ExampleCtrl',
    controllerAs: 'vm'
})
export default class ExampleCtrl {
    constructor() {
       this.init();
    }

    init() {
    }
}

// app.js
import { decoratedModule } from 'angular-utils/utils';
import AppCtrl from './AppCtrl';

export default decoratedModule('App', [])
.routerAll()
.controller(`AppCtrl`, AppCtrl)
.name;

注意: 关于 UI-Router 多命名视图配置

class TicketList {
}

class TicketDetail {
}

let routerConf = {
	url: '/ticket',
	views: {
		'': {
			templateUrl: './src/app/ticket/ticket.html',
			controller: 'TicketController',
			controllerAs: 'vm'
		},
		'list@ticket': {
			templateUrl: './src/app/ticket/list/list.html',
			controller: TicketList,
			controllerAs: 'vm'
		},
		'detail@ticket': {
			templateUrl: './src/app/ticket/detail/detail.html',
			controller: TicketDetail,
			controllerAs: 'vm'
		}
	}
};

@Router('ticket', routerConf)
class TicketController {
	constructor() {
	}
}
  • @$Timeout
import { $Timeout } from 'angular-utils/decorators';

class AppCtrl {
	@$Timeout(0, false)
	test() {
	
	}
}
  • @$Apply
import { $Apply } from 'angular-utils/decorators';

class AppCtrl {
	@$Apply
	test() {
	
	}
}
  • @$Async
import { $Async } from 'angular-utils/decorators';

class AppCtrl {
	@$Async
	async test() {
		const result = await fetchSomeInfos();
		this.info = result.info;
	}
}
  • @$Inject

依赖注入

import { $Inject } from 'angular-utils/decorators';

@$Inject('$q', '$scope')
class AppCtrl {
	constructor() {
		// 使用注入对象
		this._$q;
		this._$scope;
	}
}

依赖注入与继承

@$Inject('$rootScope')
class SuperCtrl {
	constructor() {
	}
}

@$Inject('$q')
class AppCtrl extends SuperCtrl {
	constructor() {
		super();
	}
	
	test() {
		// 使用注入对象
		this._$q;
		this._$rootScope;
	}
}

  • @Mixin
import { Mixin } from 'angular-utils/decorators';

const obj = {
   myMethod(){
   }
}

@Mixin(obj)
class MainCtrl {
    constructor() {
        this.myMethod();
    }
}
  • @InjectServices 注意 InjectService 无法注入 $scope, 因为 $scope 不是 service
import { InjectServices } from 'angular-utils/decorators';

@InjectServices('$state', '$log', '$stateParams', '$filter')
export default class PartialPage {
	constructor(title) {
		this.title = title;
	}
	
	init() {
		// 使用注入的服务
		this._$state.go(/*...*/);
	}
}

使用 utils

  • injectHelper.injector

备注: 使用该方法前:

import ngUtils from 'angular-utils/module';
angular.module('app', [ngUtils]); 

获取 $inject 对象, 方便获取依赖

import injectHelper from 'angular-utils/utils/injectHelper';

injectHelper.injector.get('$http');
  • InterceptorFactory

由于 $resource 的 interceptor 配置, 不支持数组方式, 配置多拦截器. InterceptorFactory 可以实现多拦截器的效果, 例子请参考: InterceptorFactory_spec.js

import { InterceptorFactory } from 'angular-utils/utils';
  • spread

为 Promise 提供 spread 方法

import { spread } from 'angular-utils/utils';

spread();
Promise.resolve([1, 2, 3]).spread((a, b, c) => {
	expect(a).toBe(1);
	expect(b).toBe(2);
	expect(c).toBe(3);
});

当然你也可以扩展 $q 中的 Promise (可以在 run 阶段执行方法)

spread(Object.getPrototypeOf($q.defer().promise).constructor);
  • decoratedModule

包装 angular 模块方法, 不对外提供 filter/service, 原因见No Service/Filter

另外 decoratedModule 提供了 namespace 方法, 用于启用 namespace, 这时候无论是声明 controller, directive 还是 component 时候, 都会自动添加 moduleName 前缀 避免重名问题.

import { decoratedModule } from 'angular-utils/utils';
  • EventBus

用于取代 angular 原生的 $on $broadcast $emit 原因见ng中的事件订阅与发布

import { EventBus } from 'angular-utils/utils';

// 添加事件
EventBus.addEvent('customEvent');
EventBus.addEvent('customEvent2');

// 订阅事件
let listener = function () {
	// do something that you like
};

EventBus.events.customEvent.sub(listener);

EventBus.events.customEvent.sub((obj) => {
	expect(obj.test).toBe('test');
});

// 发布事件
EventBus.events.customEvent.pub({test: 'test'});

// 禁用事件
EventBus.events.customEvent.disable = true;

// 事件禁用后, 无法触发该类事件
EventBus.events.customEvent.pub({test: 'test'});

// 启用事件
EventBus.events.customEvent.disable = false;

// 删除注册的 listener 函数
EventBus.events.customEvent.clear(listener);

// 删除所有 customEvent 事件的监听函数
EventBus.events.customEvent.clear();

// 删除事件
EventBus.clear('customEvent');

// 删除所有添加的事件
EventBus.clear();

@Component@Route的使用说明

@Route

将angular注册路由的代码用装饰器统一执行

  • 下面有一段原生的路由配置:

// index.js 文件中设置路由
import angular from 'angular';
import controller from './controller';
import templateUrl from './template.html';

routerConfig.$inject = ['$stateProvider'];
function routerConfig($stateProvider) {
	$stateProvider
		.state('le.member.information', {
			url: '/le/member',
			templateUrl,
			controller,
			controllerAs: '$ctrl'
		});
	}

export default angular.module('ccms.le.member', []) // 添加子模块
			.config(routerConfig)
			.name;
  • 使用@Route的方式改造路由注册,直接在对应controller上添加装饰器

@Route支持所有原生路由的参数配置,额外添加了stateName选项用于替代state,添加了modules用于设置子模块,添加了moduleName可以自定义路由注册时模块的名称

import templateUrl from './templateUrl';
import Route, {routerHub, setModulePrefix} from './decorators/Router';

// 注册路由时,moduleName会默认使用prefix+stateName, 也可以使用moduleName选项自定义设置模块名称
// setRouterPrefx('ccms');

@Route({
	stateName: 'le.member.information',
	templateUrl,
	url: '/le/member',
	modules: []
})
export default class MemberInformation {

}
  • 还提供了routerHub和withRouter。routerHub提供类似vue-router的集中处理路由的方式。
import { routerHub } from './decorators/Route'

export default routerHub({
	stateName: 'le.card',
	url: '/card',
	template: '<ui-view></ui-view>',
	children: [{
		stateName: 'le.card.create',
		url: '/create/:planId',
		controller: createCtrl,
		templateUrl: createTpl
	}, {
		stateName: 'le.card.list',
		url: '/list',
		controller: listCtrl,
		templateUrl: listTpl
	}]
});

@Component

与@Route的涉及的思路一致,均使用装饰器的方式整合注册过程。 @Component整合了组件注册的代码

  • 下面一段代码使用原生的方式注册组件

// index.js
import angular from 'angular';

import templateUrl from '../base/template.html';
import controller from './controller';

const componentOpts = {
  controller,
  templateUrl,
  bindings: {
    vAlign: '@?', // 垂直对齐
    hAlign: '@?', // 水平对齐
    styleObj: '<?', // 自定义样式
    className: '@', // 自定义类
    gap: '<?' // 内间距
  },
  transclude: true
};

export default angular
  .module('ccms.components.VGroup', [])
  .component('vGroup', componentOpts)
  .name;
  • 对应的,使用@Component的方式注册组件

import GroupBase from '../base/base-controller';
import {Inject} from 'angular-es-utils';
import Component from '../../../sdk/utils/easy-component';
import templateUrl from '../base/template.html';

@Component({
  name: 'vGroup',
	templateUrl: templateUrl,
	bindings: {
		vAlign: '@?', // 垂直对齐
		hAlign: '@?', // 水平对齐
		styleObj: '<?', // 自定义样式
		className: '@', // 自定义类
		gap: '<?' // 内间距
	},
 transclude: true
})
@Inject('$transclude', '$element', '$compile', '$scope')
export default class VGroup extends GroupBase {
	constructor(){
		super();
	}
}

除了添加额外的name选项用于设置组件名称,支持原生注册组件的所有选项,组件名称使用驼峰形式,否则无法渲染。