欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 编程资源 > 综合教程 >内容正文

综合教程

angular1.x es6开发风格记录 -凯发k8官方网

发布时间:2023/10/11 综合教程 49 老码农
凯发k8官方网 收集整理的这篇文章主要介绍了 angular1.x es6开发风格记录 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

一、module

es6有自己的模块机制,所以我们要通过使用es6的模块机制来淡化ng的框架,使得各业务逻辑层的看不出框架的痕迹,具体的做法是:
  • 把各功能模块的具体实现代码独立出来。
  • module机制作为一个壳子,对功能模块进行封装。
  • 每个功能分组,使用一个总的壳子来包装,减少上级模块的引用成本。
  • 每个壳子文件把module的name属性export出去。
举例来说,我们有一个modulea,里面有servicea,serviceb,那么,就有这样一些文件:
servicea的实现,service/a.js
export default class servicea {}

serviceb的实现,service/b.js

export default class serviceb {}

modulea的壳子定义,modulea.js

import servicea from './services/a';
import serviceb from './services/b';
export default angular.module('modulea'[])
.service('servicea', servicea)
.service('serviceb', serviceb)
.name;

存在一个moduleb要使用modulea:

import modulea from './modulea';
export default angular.module('moduleb', [modulea]).name;

二、controller

ng1.2开始提供了controlleras的语法,自此controller终于能变成一个纯净的viewmodel(视图模型)了,而不像之前一样混入过多的$scope痕迹。
例如:
html



controller appctrl.js

export default class appctrl {
constructor() {
this.name = 'angualr$es6';
}
getname() {
return this.name;
}
}

module

import appctrl from './appctrl';
export default angular.module('app', [])
.controller('appctrl', appctrl)
.name;

三、component(directive)

指令主要包含了一个ddo(directive definition object),所以本质上这是一个对象,我们可以给它构建一个类。
export default class directivea {}

ddo上面的东西大致可以分为两类,属性和方法,所以就在构造函数里这样定义:

constructor() {
this.template = template;
this.restrict = 'e';
}

接下来就是controller和link,compile等函数了,比如controller,可以实现一个普通的controller类,然后赋值到controller属性上来:

this.controller = controllera;

写directive的时候,尽量使用controlleras这样的语法,这样controller可以清晰一些,不必注入$scope,而且还可以使用bingtocontroller属性,把在指令attr上定义的值或方法传递到controller实例上来。接下来我们使用三种方法来定义指令


1、定义一个类(ddo),然后在定义指令的工厂函数中返回这个类的实例。

我们要做一个日期控件,合起来就是这样
import template from '../template/calendar.html';
import calendarctrl from '../controllers/calendar'; import '../css/calendar.css'; export default class calendardirective{
constructor() {
this.template = template;
this.restrict = 'e'; this.controller = calendarctrl;
this.controlleras = 'calendarctrl';
this.bingtocontroller = true; this.scope = {
mindate: '=',
maxdate: '=',
selectedate: '=',
dateclick: '&'
};
} link(scope) {
//这个地方引入了scope,应尽量避免这种做法,
//但是搬到controller写成setter,又会在constructor之前执行
scope.$watch('calendarctrl.selectedate', newdate => {
if(newdate) {
scope.calendarctrl.calendar.year = newdate.getfullyear();
scope.calendarctrl.calendar.month = newdate.getmonth();
scope.calendarctrl.calendar.date = newdate.getdate(); }
});
}
}

然后在module定义的地方:

import calendardirective from './directives/calendar';
export default angular.module('components.form.calendar', [])
.directive('sncalendar', () => new calendardirective())
.name;

2、直接定义一个ddo对象,然后传给指令

同样以datepicker组件为例,先定义一个controller
// datepickerctrl.js
export default class datepickerctrl {
$oninit() {
this.date = `${this.year}-${this.month}`;
} getmonth() {
...
} getyear() {
...
}
}

注意,这里先写了controller而不是link/compile方法,原因在于一个数据驱动的组件体系下,我们应该尽量减少对dom操作,因此理想状态下,组件是不需要link或compile方法的,而且controller在语义上更贴合mvvm架构。

在模块定义的地方我们可以这样使用:
import template from './date-picker-tpl.html';
import controller from './datepickerctrl'; const ddo = {
restrict: 'e',
template, //es6对象简写
controller,
controlleras: '$ctrl',
bingtocontroller: {
year: '=',
month: '='
} }; export default angular.module('components.datepicker', [])
.directive('datapicker', ddo)
.name;

在整个系统设计中只有index.js(定义模块的地方)是框架可识别的,其它地方的业务逻辑都不应该出现框架的影子,这样方便移植。


3、component

1.5之后提供了一个新的语法moduleinstance.component,它是moduleinstance.directive的高级封装版,提供了更简洁的语法,同时也是未来组件应用的趋势。例如
bingtocontroller -> bindings的变化,而且默认controlleras = ‘$ctrl’,但是它只能定义自定义标签,不能定义增强属性,而且component定义的组件都是isolated scope。

1.5版本还给组件定义了相对完整的生命周期钩子,而且提供了单向数据流的方式,以上例子可以写成下面这样子:

//directivecontroller.js
export class directivecontroller {
$oninit() { } $onchanges(changesobj) { } $ondestroy() { } $postlink() { }
} //index.js
import template from './date-picker-tpl.html';
import controller from './datepickerctrl'; const ddo = {
template,
controller,
bindings: {
year: '<',
month: '<'
}
}; export default angular.module('components.datepicker', [])
.component('datepicker', ddo)
.name;

4、服务

先来说一下在es6中通过factory和service来定义服务的方式。
servicea的实现,service/a.js
export default class servicea {}

servicea的模块包装器modulea的实现

import servicea from './service/a';
export angular.module('modulea', [])
.service('servicea', servicea)
.name;

factorya的实现,factory/a.js

import entitya from './model/a';
export default function factorya {
return new entitya();
}

factorya的模块包装器modulea的实现

import factorya from './factory/a';
export angular.module('modeulea', [])
.factory('factorya', factorya)
.name;

对于依赖注入我们可以通过以下方式来实现:

controller/a.js
export default class controllera {
constructor(servicea) {
this.servicea = servicea;
}
} controllera.$inject = ['servicea'];

import controllera from './controllers/a';
export angular.module('modulea', [])
.controller('controllera', controllera);

对于constant和value,可以直接使用一个常量来代替。

contant.js
export const version = '1.0.0';

5、filter

angular中filter做的事情有两类:过滤和格式化,归结起来就是一种数据的变换工作,过度使用filter会让你的额代码在不自知的情况下走向混乱。所以我们可以自己去写一系列的transformer来做数据处理。
import { dateformatter } './transformers';
export default class controller {
constructor() {
this.data = [1,2,3,4]; this.currency = this.data
.filter(v => v < 4)
.map(v => '$' v); this.date = date.now();
this.today = dateformatter(this.date);
}
}

6、消除$scope,淡化框架概念

1、controller的注入

1.2之后有了controlleras的语法,我们可以这么写。



xxx.controller("testctrl", [function() {
this.aaa = 1;
}]);

实际上框架会做一些事情:

$scope.testctrl = new testctrl();

对于这一块,把那个function换成es6的类就可以了。

2、依赖属性的计算

在$scope上,除了有$watch,$watchgroup,$watchcollection,还有$eval(作用域上的表达式求值)这类东西,我们必须想到对它们的替代办法。
一个$watch的典型例子
$scope.$watch("a", function(val) {
$scope.b = val 1;
});

我们可以直接使用es5的setter和getter来定义就可以了。

class a {
set a(val) { //a改变b就跟着改变
this.b = val 1;
}
}

如果有多个变量要观察,例如

$scope.$watchgroup(["firstname", "lastname"], function(val) {
$scope.fullname = val.join(",");
});

我们可以这样写

class controller {
    get fullname() {
return `${this.firstname} ${this.lastname}`;
}
}

html



3、事件冒泡和广播

在$scope上,另外一套常用的东西是$emit,$broadcast,$on,这些api其实是有争议的,因为如果说做组件的事件传递,应当以组件为单位进行通信,而不是在另外一套体系中。所以我们也可以不用它,比较直接的东西通过directive的attr来传递,更普遍的东西用全局的类似flux的派发机制去通信。

根作用域的问题也是一样,尽量不要去使用它,对于一个应用中全局存在的东西,我们有各种策略去处理,不必纠结于$rootscope。

4、指令中$scope

参见上文关于指令的章节。

7、总结

对于整个系统而言,除了angular.module,angular.controller,angular.component,angular.directive,angular.config,angular.run以外,都应该实现成与框架无关的,我们的业务模型和数据模型应该可以脱离框架而运作,当做完这层之后,上层迁移到各种框架就只剩下体力活了。

一个可伸缩的系统构架,确保下层业务模型/数据模型的纯净都是有必要的,这样才能提供上层随意变化的可能,任何模式下的应用开发,都应具备这样一个能力。

参考链接:



















总结

以上是凯发k8官方网为你收集整理的angular1.x es6开发风格记录的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

  • 上一篇:
  • 下一篇:
网站地图