angular1常用组件和服务的设计思路

每个Angular“应用程序”ng-app都有一个 injector ,负责创建并查找依赖,当缓存中没有依赖key1时,记依赖对象为{key1:null,key2:value2,...},后来当key1出现时,key1修改依赖对象为{key1:value1,key2:value2,...},所有文件加载完毕以后,执行全局配置函数config和run,如果所有文件加载完毕,key1也没有出现,则会报错,不会执行全局配置函数。
一、标题组件的设计思路:
1、标签内属性传参
(1)标题内容
2、模板
(1)<img ng-src="{{‘./title.png‘}}">
(2)<span>{{title}}</span>
3、控制器(空),link(空)

二、局部加载组件的设计思路:
1、标签内属性传参
(1)图片名称
(2)是否旋转
(3)是否出现
2、模板
(1)<img ng-src="{{‘./‘+name+‘.png‘}}">
3、控制器(空),有link
(1)如果旋转,使用ele.addClass(""),也可以ele.css({})

三、全局加载组件的设计思路:
1、标签内属性传参(无)
2、模板
(1)根标签,是否显示(由请求结果赋值)、class(蒙版和蒙版下的图片)
(2)子标签,A、局部加载组件的标签,标签内有属性传参图片名称、旋转class,B、文字提示
3、控制器(空),link(空)

四、全局提示组件的设计思路和全局提示服务:
1、标签内属性传参(无)
2、模板
(1)根标签,class(蒙版和蒙版下的图片)
(2)子标签,遍历数组,绑定提示文字
3、控制器
(1)接收全局提示服务
4、全局提示服务
(1)定义空数组和提示对象
(2)定义设置函数,参数为提示内容,在函数内部把提示内容放进提示对象、把提示对象放进空数组、执行单次定时器(遍历数组,删除数组中的该提示对象)

五、开关组件的设计思路
1、标签内属性传参
(1)参数1为是否受其它开关控制的数据,此参数定义在控制开关里
(2)参数2为本条数据,包含控制本开关的参数,也可能有向后台发送请求的回调函数
2、模板
(1)可变化的图片名,图片名和参数2中控制开关的属性相关联,比如:ng-src="{{‘./‘+config[data.value]+‘.png‘}}"
(2)点击函数执行
3、控制器
(1)配置图片名,$scope.config = { 0: ‘switch-off‘}
(2)定义点击函数,内有$scope.data.value = 0
4、定义点击函数时,应考虑的因素
(1)是否受其它开关控制
(2)是否向后台发送请求、根据请求结果给控制开关的参数赋值;
(3)给控制开关的参数赋值

六、一个复杂页面的逻辑
1、页面构成
(1)带参数跳转至本页面
(2)过滤条件
(3)本页需记录单选、全选、所有页全选
(4)含交互和分页的弹窗
(5)分页
(6)请求数据时,有局部转圈和全局转圈
(7)刷新时,有刷新成功或失败的提示
2、页面逻辑
(1)在分页服务里,配置本页面除初始化以外的路由,
(2)将全选服务、分页服务、二者的结合,放在一个服务里,注入本页面,把本页面的作用域传入该服务的方法里并执行,给本页面配置公用的属性和方法。
(3)页面初始化时先正常渲染,再根据是否有参数来决定:过滤条件是否展开、过滤条件的默认值、是否进行二次渲染。
(4)把本页面中与分页相关的属性通过属性传参的方式传给分页组件,在分页组件里定义请求函数,这个函数还可以在本页面和分页服务里被调用。
(5)在请求服务里,让转圈出现和消失;一个事件两次请求时,两个请求的结果都返回后,让转圈消失。
3、相关代码如下
```javascript
(function () {
angular
.module(‘module-policy‘)
.controller(‘policyWhiteOrderCtrl‘, function ($scope, tradeApi, $stateParams,clickCheckbox) {
$scope.currentPageDatas = new clickCheckbox.init(‘whiteListId‘);
$scope.broadcastToPagination = {
filter_option:{},/*页面过滤条件*/
start_filter:function(callback){
this.reload()
},/*过滤函数,公用*/
url:‘seclity/wlist/getinfo‘,
page:‘page_total‘,/*统一参数名称*/
totalPage:‘page_total‘,/*统一参数名称*/
total:‘datas_total‘,/*统一参数名称*/
callback:function (res) {/*分页请求执行完后,调用的回调*/
$scope[‘list‘] = res.wlists;
$scope[‘toPaginationDatas‘][‘cust‘] = [{/*以下可以有,配置到分页里,可在分页里获取*/
txt: ‘已启用‘,
data: res.deployed_total,
unit: ‘条,‘
}];
$scope.currentPageDatas.page($scope[‘list‘], res.datas_total);
}
};
$scope.init = function (type) {
var request_param = {
method: ‘post‘,
root: ‘seclity‘,
url: ‘/wlist/getinfo‘,
params: {
pageNum: 1
},
scope: {
scope: $scope,
initload_key: ‘initload‘
},
load: $scope.broadcastToPagination.load(3)
};
if (type === ‘reload‘) delete request_param.load;
tradeApi
.query(request_param)
.then(function (res) {
$scope.list = res.wlists;
$scope.toPaginationDatas = {/*这里面的数据很少*/
cust: [{/*以下可以有,配置到分页里,可在分页里获取*/
txt: ‘已启用‘,
data: res.deployed_total,
unit: ‘条,‘
}],
/*以下必须有,注入到分页里,可在分页里获取*/
page: res.page_current,
totalPage: res.page_total,
total: res.datas_total
};
$scope.pre_params_fun();
});
tradeApi
.query({
method: ‘get‘,
root: ‘seclity‘,
url: ‘/wlist/get_protocol‘
})
.then(function (res) {
$scope.select_option.protocol = [];
angular.forEach(res.protos, function (item) {
$scope.select_option.protocol.push({
v: item,
k: item
})
})
});
};
$scope.pre_params_fun = function () {
var target = $stateParams.target;
if (target === null) return;
$scope.broadcastToPagination.filter_option_toggle($scope.broadcastToPagination.reload);
$scope.broadcastToPagination.filter_option.protocolType = target;
$scope.broadcastToPagination.start_filter($scope.currentPageDatas.init)
};
});
})();
/*以下是:分页组件里的请求函数*/
$scope.query = function (page_index, type) {
tradeApi
.query({
method: $scope.emitToCurrentPageDatas.query_method,
root: $scope.emitToCurrentPageDatas.query_root,
url: $scope.emitToCurrentPageDatas.query_url,
data: $scope.set_query_params(page_index),
params: $scope.set_query_params(page_index),
load: {
table: function (boolen) {
$scope.emitToCurrentPageDatas.tableload = boolen;
}
}
})
.then(function (res) {
$scope.fromCurrentPageDatas.page = res[$scope.emitToCurrentPageDatas.page];
$scope.fromCurrentPageDatas.totalPage = res[$scope.emitToCurrentPageDatas.totalPage];
$scope.all_pages_add();
$scope.fromCurrentPageDatas.total = res[$scope.emitToCurrentPageDatas.total];
if (type === ‘reload‘) {
dir_tip.set({
msg: ‘刷新成功!‘
})
}
$scope.emitToCurrentPageDatas.callback(res);
})
};
$scope.emitToCurrentPageDatas.reload=function(){
$scope.query()
};
```

七、弹窗组件的设计思路和弹窗服务:
注意:所有的弹窗,框架都是一样的,有些内容没显示,是因为各自ng-show的值被设置为false。
1、代码
(1)html
```html
<div id="dir-alert">
<div class="dir-alert-model" ng-if="alert.isShowModel" ng-click="clickMask()"></div>
<div class="dir-alert-wrap" ng-show="alert.isShowModel" ng-style="alert.width">
<div class="dir-alert-title">
<span ng-bind="alert.title"></span>
<em ng-click="clickClose()" ng-show="alert.isShowIcon"></em>
</div>
<div class="dir-alert-content">
<div ng-bind="alert.tipText"></div>
<div id="dir-alert-html"></div>
</div>
<div class="dir-alert-button" ng-show="alert.isShowFooter">
<input ng-bind="alert.cancelText" style="margin-right:15%" ng-click="alert.clickCancel()"
ng-hide="alert.isCancelTextShow" type="button" class="btn btn-outline-primary"/>
<input ng-click="alert.clickConfirm()" ng-hide="alert.isShowConfirmText" type="button"
class="btn btn-outline-danger dir-alert-ok" value="{{alert.confirmText}}"/>
</div>
</div>
</div>
```
(2)js
```javascript
angular.module(‘common-dir‘)
.directive(‘dirAlert‘, function () {
return {
restrict: ‘E‘,
templateUrl: ‘module/common-directive/dir-alert.html‘,
scope: {},
controller: function ($scope, dir_alert) {
$scope.alert = dir_alert;
$scope.clickMask = function () {
if ($scope.alert.isShowMask) {
$scope.alert.isShowModel = false;
}
};
$scope.clickClose = function () {
$scope.alert.isShowModel = false;
}
},
link: function (scope, ele) {
}
};
})
```
(3)服务
```javascript
angular.module(‘common-dir‘)
.factory(‘dir_alert‘, function ($sce, $compile, $rootScope) {
return {
isShowModel: false,
width: {width: ‘300px‘},
title: ‘系统消息‘,
isShowIcon: true,
tipText: ‘‘,
confirmText: ‘确定‘,
cancelText: ‘取消‘,
isShowConfirmText: false,
isShowMask: true,
isShowFooter: false,
isCancelTextShow: false,
clickCancel: function () {
this.isShowModel = false;
},
tipHtml: ‘‘,
tipHtmlAllMehtods: {},
alertSet: function (parameterObject) {
var that = this;
parameterObject.isShowModel = true;
that.tipText = ‘‘;
angular.element(document.getElementById(‘#dir-alert-tipHtml‘)).empty();
that.tipHtml = parameterObject.tipHtml || false;
that.tipHtmlAllMehtods = parameterObject.tipHtmlAllMehtods || ‘‘;
if (that.tipHtml && that.tipHtmlAllMehtods) {
that.tipHtmlScope = $rootScope.$new();
angular.extend(that.tipHtmlScope, that.tipHtmlAllMehtods);
angular.element(document.getElementById(‘#dir-alert-tipHtml‘)).empty().append($compile(angular.element(that.tipHtml))(that.tipHtmlScope));
}
parameterObject.clickConfirm = function () {
angular.isFunction(clickConfirmCallback) ? clickConfirmCallback() : angular.noop();
that.isShowModel = false;
};
parameterObject.clickCancel = function () {
angular.isFunction(clickCancelCallback) ? clickCancelCallback() : angular.noop();
that.isShowModel = false;
};
angular.isObject(parameterObject) ? angular.extend(that, parameterObject) : ‘‘;
}
};
});
```
(4)应用
```javascript
$scope.detail_alert = function (single) {
dir_alert
.alertSet({
width: { width: ‘1000px‘},
tipTitle: single.protocolType + ‘协议分析详情‘,
tipHtml:
‘<table class="table table-bordered table-hover common-cust-table">‘ +
‘<thead><tr><th ng-repeat="li in result.title track by $index"><button class="btn" ng-bind="li"></button></th></tr>‘ +
‘</thead>‘ +
‘<tbody><tr ng-repeat="lis in list2 track by $index"><td ng-repeat="li in lis track by $index" ng-bind="li"></td></tr>‘ +
‘</tbody>‘ +
‘</table>‘ +
‘<dir-tableload show="detail_pagin_init.tableload"></dir-tableload>‘ +
‘<dir-pagination config="detail_pagin_init" pagination-config="detail_pagin_config" ></dir-pagination>‘,
tipHtmlAllMehtods: {
init: function () {
var that = this;
tradeApi
.query({
method: ‘post‘,
root: ‘icaudit‘,
url: ‘/protsis/get_detail‘,
data: {
id: single.id,
}
})
.then(function (res) {
that.result = res;
that.list2 = res.data;
});
}
}
});
};
```
八、复选框服务:
1、各种初始化,比如单选状态初始化、当前页全选状态初始化、所有页全选状态初始化、被选中项数组初始化、被选中项取消选中数组初始化;
2、各种点击函数,比如点击单选函数、点击当前页全选函数、点击所有页全选函数、获取所有被选中项id函数;

九、请求服务设计思路(requestServer)
1、获取异步请求对象
(1)var deferred = $q.defer();
2、发送前确认
(1)点击"取消",仅弹窗消失,没有其他操作
(2)点击"确认",继续发送请求,实参为allParams和deferred
(3)如果没有发送前确认,则直接发送请求that.sendServer(allParams, deferred);
3、返回异步请求实例
(1) return deferred.promise;
4、封装sendServer函数
(1)this.http = function (allParams, deferred) {}
(2)allParams内有固定参数:method、url、toServerParams、stayLocalParams
(3)allParams内有可有参数:responseType、loading、其它可有参数
(4)调用$http服务,正式发送请求,定义返回函数
5、定义$http服务的返回函数
(1)根据stayLocalParams执行注入的成功函数
(2)根据返回值,判断过期,用弹窗弹出错误提示,2秒后跳往登录页面
(3)根据返回值,判断请求成功,用弹窗弹出成功提示,点击后,弹窗消失
(4)根据返回值,判断请求失败,执行注入的失败函数
(5)以上情形过后,再执行一次注入的成功函数
6、执行finally函数,取消4(3)中的loading
7、定义注入函数,由具体的使用场景提供

附:项目总脉络,index.html=> main.js=> common-dir模块及其下标签=> ui-view => login
1、定义应用模块 angular.module(‘app‘, [])
2、在模块加载阶段执行,对模块进行自定义配置 angular.config(function ($urlRouterProvider) { $urlRouterProvider.otherwise(‘/login‘);})
(1)登陆成功后,根用户=返回的用户信息、sessionStorage.setItem(根用户,返回的用户信息)
(2)根据返回的用户信息,给左侧导航栏赋值
(3)状态go为导航栏第1栏第1个选项卡
3、angular应用最先执行的方法,只在启动的时候运行一次,定义全局的数据或逻辑
```javascript
angular.run(function ($rootScope) {
/*此处可以初始化全局变量*/
$rootScope.$on(‘$stateChangeStart‘,
function (event, toState) {
/*状态即将改变时,执行此函数
1、先检查用户名,如果用户名为空,则跳往登录页面
2、点击当前页的跳转,如果前往的状态不存在,则阻止默认事件并且给出弹窗提醒*/
}
);
$rootScope.$on(‘$stateChangeSuccess‘,
function (event, toState) {
/*状态改变完成时,执行此函数
1、当前状态=目标状态,在HTML页面,如果点击函数(item)中item.state===当前状态,那么改变item的样式
2、根选项卡=item.sub,在HTML页面,遍历根选项卡*/
}
);
})
```
4、页面右上方有退出登录按钮,
(1)退出成功后,根用户=null、sessionStorage.removeItem(根用户)
(2)状态go为登录
5、导航栏和选项卡关联
(1)遍历左侧导航栏,绑定文字内容、点击函数(item)、样式;
(2)点击函数(item),根选项卡=item.sub;

附:点击表格某一项,再出详情表格
1、情形描述
(1)“表格”最左列有图标向右,表示该项数据可以展开
(2)点击图标向右,则其他图标向下变为向右且下拉表格收起,同时该图标向右变为图标向下,向后台发送请求,返回的数据如果是空数组则该页面右下方出现提示,如果不是空数组则该行出现下拉表格
2、情形实现
(1)HTML:遍历原始数据为主表格每一项,通过name="li.id==id?‘a.png‘:‘b.png‘"决定图片名称,通过ng-show="li.isMaster===‘1‘"决定是否显示图片
(2)HTML:在主表格每一项的下面,遍历返回的数据为下拉表格的每一项,通过ng-show="li.id==id"决定在主表格的哪项下面展开下拉表格
(3)JS:定义id
(4)JS:定义点击函数,依次清空返回的数据、如果id === li.id则置空id且阻断执行、id === li.id、向后台发送请求并获取返回值、如果返回空数组则给出提示(否则返回数据)
3、总逻辑
(1)把该“行”数据itemData传入点击函数,在函数内部,获取itemData.id并向后台发送请求,把获取的返回值作为itemData.itemDetail的属性值,这样就把返回值与具体的“行”相关联;
(2)在详情表格内遍历itemData.itemDetail;

附2、登录页面交互思路:
1、登录页面有四项内容:登录名、密码、验证码、登录;
2、登录页面打开时,光标定位在登录名;
3、在前三项内容的任何一项触发“enter”键,则检验它前面及自身的项是否为空,如果为空则给出提示,并将光标聚焦在该处,如果不为空则将光标聚焦在下一项,如果下一项为“登录”,则执行登录函数;
4、点击“登录”时,也执行登录函数;
5、定义登录函数,(1)检查前三项四否有空项,(2)如果有空项则给出提示,并将光标聚焦在该项,(3)如果没有空项,则向后台发送请求;
6、如果后台返回1,则提示用户名不存在,光标定位到用户名;如果后台返回2,则提示密码错误,光标定位到密码;如果后台返回3,则提示验证码错误,光标定位到验证码;如果返回4,则登录成功。

原文地址:https://www.cnblogs.com/gushixianqiancheng/p/10962941.html

时间: 2024-11-09 03:12:49

angular1常用组件和服务的设计思路的相关文章

TYPESDK手游聚合SDK服务端设计思路与架构之一:应用场景分析

TYPESDK 服务端设计思路与架构之一:应用场景分析 作为一个渠道SDK统一接入框架,TYPESDK从一开始,所面对的需求场景就是多款游戏,通过一个统一的SDK服务端,能够同时接入几十个甚至几百个各种渠道的SDK.而且这些渠道接口的具体接入字段和接入逻辑,每个月以至每周,都可能发生或大或小的变动.在这样一个复杂的应用场景下,我们应该如何设计一个足够强大而又足够灵活的SDK服务端呢? 首先我们需要厘清,在整个应用场景中,TYPESDK所处的位置,以及它所需要实现的核心功能. 图1 如图1所示,T

JS表格分页组件:fupage的设计思路和具体用法(未来考虑开源,争取在2015年)

一.背景         之前在秒针工作的时候,某js高级工程师写了很多自己的组件,其中一套是分页组件,叫做st-grid.不过在我看来,bug太多,我经常给他反馈bug,我也不清楚为啥别人没有发现.    回到武汉工作后,我自己利用业余实践完善自己的官网,从前端到后端,都是自己一个人亲自搞定.    第1个分页的需求是,文章下方的评论,异步加载.第2个需求是,表格管理,比如后台管理系统,经常需要列出user.log等表的记录.   二.实例 <table class="table tab

TYPESDK 服务端设计思路与架构之六:性能及调优初步

经过本系列前几篇文字的分析和设计,我们成功地开发出了自己的SDK服务端.在我们自己的调试环境下运行一切正常,但是当然我们不能就这样把这套SDK服务端部署上线到正式生产环境,稍有正式大型项目经验的同学应该都知道性能优化以及部署上线相关设计对于服务端项目的重要性.我们到目前为止的分析设计中,并没有考虑到这些设计.那么,针对我们SDK服务端这样的应用场景,应该着重关注哪些相关的优化和设计呢? 数据存取优化 在我们的应用场景中,需要使用到存储的场景主要在以下几个处理中: l  获取配置信息 对每个收到的

头像服务端设计思路

思路 一 把图片上传到服务端.命名以用户的(用户名md5)作为文件名.要是以前有文件,覆盖以前的文件 二编写一个servlet处理获取头像请求. servlet接收一个用户名md5+大小的参数 根据 用户名md5+大小生成对应的图片 例如 用户名为ada 上传到服务端的位置为 /gravatar/ada.jpg 请求地址:/webstore/headimg/ada.jpg?s=120 对应的服务端文件地址 /gravatar/ada.jpg(原图片) /gravatar/ada/120.jpg

TYPESDK手游聚合SDK服务端设计思路与架构之三:流程优化之订单保存与通知

经过前两篇文字的分析与设计,我们已经可以搭建出一个能够支持多游戏多渠道的聚合SDK服务端,但这只是理想化状态下的一个简化模型.如果接入渠道的逻辑都是按照理想化的简化过程来构建,那么对于支付的请求,我们可以简化成这样几步: 游戏客户端创建订单. 游戏客户端(通过TYPESDK客户端)调用渠道lib库中相应接口,发起支付. 用户在弹出的支付窗口完成支付. TYPESDK服务端等待渠道服务端的回调,收到回调后通知游戏服务端. 游戏服务端执行发货动作. 但是显然这个简化流程在实际上线时是不够满足需求的,

流程管理中WEB表单开发服务需求分析及设计思路

在流程管理应用中,BPM产品所提供的表单设计工具,主要是面向开发人员的.而一些办公系统产品所提供的表单设计工具,受自身平台限制,无法在大型定制化应用中使用.在此通过对用户需求分析,提出WEB表单开发服务设计思路. 一.需求分析 现如今,在创新与改革社会环境推动下,办公管理系统的管理需求变化已经是常态了,如何让信息系统快速响应支撑管理需求的多变,已经成为使信息化建设和运维人员头痛的事情.特别是在一些大型企事业单位,快速支撑需求更突出.而原有信息系统很难适应这样的需求,必须走创新的路来解决这些需求,

原创:GridView组件(二):设计思路

GridView组件(二):设计思路 上期回顾:http://www.cnblogs.com/beiou/p/4113327.html 1.页面结构: gridview表格本生是可以只用一个table来渲染的. 但是为了结构清晰,便于维护,同时需实现table自行滚动且横向滚动colHead,分为四块: (1)colHead列头Panel (2)table数据Panel (3)page分页Panel (4)Drag拖拽线Panel覆盖在colHeadPanel与tablePanel之上. 2.对

高并发高可用服务设计思路

高并发高可用服务设计思路 原文地址:https://www.cnblogs.com/linjiqin/p/9193774.html

Redis设计思路学习与总结

版权声明:本文由宋增宽原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/222 来源:腾云阁 https://www.qcloud.com/community 宋增宽,腾讯工程师,16年毕业加入腾讯,从事海量服务后台设计与研发工作,现在负责QQ群后台等项目,喜欢研究技术,并思考技术演变,专注于高并发业务架构的设计与性能优化. 下半年利用空余时间研究和分析了部分Redis源码,本文从网络模型.数据结构和内存管理.持久化和多机