任务分解

对于一个程序媛来说,如何提高自己的开发效率,这一直都是我追寻的方法。直到最近才get到一个可以有所帮助的技能。

任务分解,列Task

当我们拿到一个任务卡片时,经常干的一件事,就是明确卡片中的要求和明细,然后就直接开始码代码了。因为写的代码是可见的,运行成功会有极大成就感,然而其实这并不是一个好的方式。

在我们写代码之前应该根据卡片内容,从开发的角度把一个大卡分解成各个小任务,然后针对每个小任务进行开发才是可取的。其实这种方法得到的成就感并不亚于前者。

Task 是什么,如何列

很多人会和我一样困惑,要列Task,但是什么是Task呢?一般来说,一个function(函数),一个Process或者一个Code Block(代码块)都可以是一个Task。
每一个Task都有相应的输入和输出。输入的可以是函数的参数,全局变量,局部变量(对于代码块来说)。输出可以是返回值,变量等。

每个Task的输入都是可穷尽的,在列Task的时候要列出所有用到的Task。
列Task的时候的命名要精确,每一个名字在不同的地方有不同的意思。

列Task,一般会画一个包含Data和Process的图。类似一个有架构的数据流向图。Data(数据)一般有数组、队列、栈、树、对象、类、有循环的对象等,Process(过程)一般有顺序的、选择的(if/switch)、循环(for/while)等。

参考
编程的精进之法

PDCA 戴明环

PDCA指的是Plan-Do-Check-Action,而列Task属于Plan的内容。

如何定义Done?
1.code Done
2.test pass
3.Integration env
4.showcase
5.production env
6.ux(用户使用)

单个任务的开发流程:0)Spike即调研;1)写测试;2)写实现;3)测试通过

例子一,打印学生成绩单

背景:

https://www.zybuluo.com/jtong/note/471501 中的课后作业
打印所有人的成绩单,包括平均分和总分。
打印全班级的总分平均分和中位数。

列Task

1) 转换ViewModel

输入:

studentScoresArray:[[String]]

输出:

studentScoresSheet:[{
    name:String,
    chinese:double,
    english:double,
    math:double,
    programming:double
    },
    {
    ...
    }]
2) 得到学生成绩

输入:

studentScoresSheet

输出:

studentScoresSheetWithSummary:[{
    name:String,
    chinese:double,
    english:double,
    math:double,
    programming:double,
    average:double,
    total:double
    },
    {
     ...
    }]
3) 计算总计

输入:

studentScoresSheetWithSummary

输出:

summary:{
    totalAverage:double,
    totalMidden:double
    }
4) 打印成绩单

输入:

studentScoresSheetWithSummary
summary

输出:

Result:String

Github代码

例子二,猜数字游戏

具体游戏内容
这个游戏有几个需要注意点:
1)Compare(两个数字对比的前提假设:符合要求的、合法的值)
2)生成随机数(生成的数是数字、四位、每位都不一样)
3)游戏流程(进入游戏–第一次成功/中间成功/最后一次成功/游戏失败)

PS:不能放过任何一个逻辑冲突;等加类划分可以使用正交分解法;还要考虑系统状态怎么保持
正交分解法:

 \ 位   |         |         | 
  \ 置  |         |         |
数 \    | 全都一样 | 全不一样 | 部分一样
字  \   |         |         |
--------------------------------------
全都一样 | 4A0B    | 0A4B    | 2A4B
全不一样 | 不可能   | 0A0B    | 不可能
部分一样 | 不可能   | 0A2B    | 2A2B

分解后的图如下:
1)应用启动

2)界面1(按1启动游戏)

main是解决输入输出的。
Router通过输入输出解析找到具体的Command。
Command处理各种具体的用户输入,对Core层返回的结果翻译成友好的输出。
Core层函数生成计算结果。

3)退出(按2退出游戏)

例子三,邮编和条码的转化

例子四,一对多web基础应用

例子五,多对多web基础应用

ansible

因为项目需要,所以提前学习了一下ansible,ansible是一个配置管理工具。

ansible 安装

Mac OS X 上安装Ansible,如果已经有Homebrew包管理工具可以直接运行

1
brew install ansible

Python包管理工具pip安装,root 安装方式如下:

1
sudo pip install ansible

非root安装方式,可以安装到一个Python virtualenv中,或者使用pipsi工具,自动安装到Python virtualenv中。

1
2
3
wget https://raw.githubusercontent.com/mitsuhiko/pipsi/master/get-pipsi.py
python get-pipsi.py
pipsi install ansible

再将~/.local/bin添加到Path环境变量中。

使用pip安装docker-py和boto

1
2
3
cd ~/.local/venvs/ansible
source bin/actiivate
pip install docker-py boto

ps: 安装wget

1
2
3
4
5
6
7
cd Downloads
curl -O http://ftp.gnu.org/gnu/wget/wget-1.14.tar.gz
tar xvzf wget-1.14.tar.gz
cd wget-1.14
./configure --with-ssl=openssl
make
sudo make install

install wget in Mac OS X

参考install ansible on Mac
ansible官方安装文档

架构设计

最近在接受一个培训,第一次接触了架构设计的知识,有些名词晦涩难懂,导致在这一块的学习还是有所欠缺。
尽管如此,在培训中和培训后的努力学习后,做了点整理,理解的可能有所偏差,欢迎拍砖。

架构设计对于一个项目来说十分重要。

一份完整的架构设计应该包括哪些内容

1)建模,提炼资源
2)系统结构(BFF,业务流程)
3)开发团队结构
4)可用性与性能架构
5)安全性架构
6)质量架构
7)部署架构
8)运维架构
9)技术选型

面向行为的接口设计与面向资源的接口设计(ROA)

面向行为的接口设计是建立在动词(行为)的基础之上的,系统要枚举所有的业务行为,如果行为发生改变,接口也随之改变。
面向资源的接口设计便于实施、设计灵活、是轻量级的对象访问方式。
面向资源的接口设计关注的是名词(资源),解决了在业务需求发生变化时要对代码做很大的改变的问题。

SOA 面向服务的架构设计

将紧耦合的系统,划分为面向业务的,粗粒度,松耦合,无状态的服务。
目的是提高软件的重用性,减少开发和维护的成本,最终增加敏捷度。

微服务架构

微服务架构其中的一个重点是业务系统需要彻底的组件化和服务化,原来的业务可以拆分成独立的系统应用进行开发,这些相互独立的系统应用通过服务完成交互和集成。
它的目的是有效的拆分应用,实现敏捷开发和部署,为构建应用提供更轻量级、更高效的开发。

微服务不再强调传统SOA架构里面比较重的ESB企业服务总线,同时SOA的思想进入到单个业务系统内部实现真正的组件化。

微服务足够构成一个独立的小应用(从DB到UI)

微服务的基本思想在于考虑围绕着业务领域组件来创建应用,这些应用可以独立的进行开发管理和加速。在分散的组件中使用微服务云架构和平台使部署管理和服务功能交付变得更加简单。

(Devops:开发测试和部署运维一体化。)

把单体应用拆分成多个小应用后,整体架构可以松耦合和可扩展,但是当拆分的组件越多,这些组件之间本省的集成和部署运维就越复杂。
任何一个组件,当依赖的外部应用组件越多的时候,整个集成,部署和连调测试的过程就越复杂,所以自动化这个过程可以减少工作量和出错概率。

微服务架构首先要做好单个组件本身的持续集成,其次在这个基础上增加了多个组件的打包部署和组件间的集成。包括环境变量的配置,自动打包部署,自动化的测试等。

不像传统多个服务共享一个数据库,微服务架构每个服务都有自己的数据库。

一般运行在云虚拟机或者更轻的Docker上

微服务架构强调了单个组件本身可以在独立的进程里面运行,各个组件之间在部署的时候就能够做到进程级别的隔离性。
为了保持进程的隔离性,使用虚拟机,但是几十个进程都完全用独立的虚拟机就不现实,解决方案为利用Docker容器,每个Docker是独立的容器,完全做到了进程季节的隔离,资源占用率最小,满足了微服务架构的开发测试和自动化部署。

微服务应用之间只能通过Service API进行交互

单个服务的实现和发布仍然在组件内部完成,但是需要一个统一的SOA服务管理平台来显示服务本身的调用情况,服务本身的安全,日志和流量控制。
微服务强调采用HTTP Rest API的方式。
即微服务尽量通过HTTP API的方式暴露出去,因此这种服务管理平台需要基本的服务注册,服务代理,服务发布,服务简单的路由,安全访问和授权,服务调用消息和日志记录功能。

微服务架构的优势

1.通过分解巨大单体式应用为多个服务方法解决了复杂性问题。在功能不变的情况下,应用被分解为多个可管理的分支或服务。单个服务很容易开发、理解和维护。
2.每个服务都可以有专门的开发团队并行开发。
3.每个服务独立部署,不需要协调其他服务部署对本服务的影响,加快了部署速度,使得持续化部署成为可能。
4.每个服务可独立扩展。
5.每个服务足够内聚,足够小,代码容易理解、开发效率提高。
7.提高容错性,一个服务的内存泄露并不会让整个系统瘫痪。
8.可以使用多个技术栈,系统不会被技术栈长期限制。

微服务架构的不足

1.一个应用系统里面的模块没有办法做到彻底解耦,无法实现组件单独部署,相互之间有大量内部不可见依赖而导致了模块间的无法拆分。
2.微服务应用式分布式系统,会带来固有的复杂性。
3.分区的数据库架构带来的挑战,因为需要更新不同服务所使用的不同的数据库。
4.测试一个基于微服务架构的应用很复杂。
5.微服务架构模式应用的改变将会波及多个服务。
6.部署一个微服务应用也很复杂,一个分布式应用只需要简单在复杂均衡器后面部署各自的服务器就好了。每个应用实例是需要配置诸如数据库和消息中间件等基础服务。

微服务的特征:

通过服务实现组件化
按业务能力来划分服务于组织团队
服务即产品
智能终端与哑管道
去中心统一化
基础设施自动化
Design for failure
进化设计

微服务总结

一个微服务一般完成某个特定的功能,每个微服务都是一个微型应用,有着自己的六边形架构,包括商业逻辑和各种接口。
有的微服务通过暴露API被别的微服务或者应用客户端所用;有的微服务则通过UI实现。在运行时,每个实力通常时一个云虚拟机或者Docker容器。

SOA、微服务、服务化这几个概念的差别和关系

SOA服务导向架构,将应用程序功能作为服务发送给最终用户或者其他服务,是整合各种业务的应用程序。
微服务是一种以业务功能为主的服务设计,通过将功能分散到各个离散的服务中以实现对解决方案的解耦,所以每一个服务都具有自主运行的业务功能。微服务只属于一个应用程序,它要求业务系统彻底的组件化和服务化。
服务化是一种粗粒度、松耦合的以服务为中心的架构,服务之间通过定义明确的协议和接口进行通信。

好的架构应该具备的特征

基于资源的接口设计
开发团队结构要正确映射系统架构
要考虑业务架构和组织架构

参考文章:
软件架构模式
SOA和微服务的区别
微服务架构的优势与不足
解析微服务架构(一)
基于微服务的软件架构模式
组件化、模块化、集中式、分布式、服务化、面向服务的架构、微服务架构

持续集成(Continuous Integration)

在工作之前,曾经遇到过这么一个问题,和多个小伙伴一起开发,一个人负责了一大块的功能,最后在每个人完成各自的开发工作以后,集成成一个系统。
这真的是很痛苦的一件事情,没有任何的铺垫,一堆冲突,集成后也不知道系统是不是存在bug。
然而在真正工作以后,才发现了这些问题的正确打开方式。

持续集成是什么

Martin Fowler对持续集成(Continuous Integration)的定义:

Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible.Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly.

持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。

Martin Fowler对持续集成的内容概述:

Maintain a Single Source Repository.
Automate the Build
Make Your Build Self-Testing
Everyone Commits To the Mainline Every Day
Every Commit Should Build the Mainline on an Integration Machine
Fix Broken Builds Immediately
Keep the Build Fast
Test in a Clone of the Production Environment
Make it Easy for Anyone to Get the Latest Executable
Everyone can see what’s happening
Automate Deployment

1.统一的代码库。一个团队在开发过程中都需要一个代码库,每个人写的代码都更新到同一个代码库上。例如Github,Gitlab等,如此一来就需要版本管理工具例如git,svn等等。
2.自动构建。手动构建的代价太大,使用工具来自动构建。
3.自动测试。
4.每个人每天都要向代码库主干提交代码。
5.每次代码递交后都会在持续集成服务器上触发一次构建。
6.保证快速构建。
7.模拟生产环境的自动测试。
8.每个人都可以很容易的获取最新可执行的应用程序。
9.每个人都清楚正在发生的状况。
10.自动化的部署。

持续集成的好处

由上可知,持续集成的好处在于:
(1)快速发现错误。每个coder完成了一小段代码就更新集成到主干,如此一来可以快速的发现错误,并且定位错误,改正错误。
(2)使得代码不会大幅度的偏离主干。如果不经常集成代码,更新不快,最后集成的难度非常大。
(3)在任何时间、任何地点生成可部署的软件。对于客户来说,这便于持续交付。
(4)改善对进度的控制。每天都在集成,就可以看到当前各个功能的进度。
(5)更加充分地测试系统中的各个单元。
(6)与其它工具结合的持续代码质量改进。如使用CheckStyle, PMD, FindBugs, Fxcop等。
(7)便于Code Review。在每个build里,我们都可以知道与前一个build之间有什么改动,然后针对这些改动,我们就可以实施Code Review了。
(8)便于开发流程的管理。比如说,要把一个开发的build提交给测试组作测试,测完满意了,再提交到发布组去发布。

持续集成的目的,就是让产品可以保持高质量的快速迭代。

持续集成的工具

CI工具实现了每个开发人员提交代码的时候自动进行构建,包括代码审查、编译、测试、打包等操作。如此可以保证每次提交都是安全的。
CI工具还可以提供事件通知,生成报告等。例如当某一步构建失败了发送通知给指定的email、通过特定的设置发出声音等。
常见的工具有:
Jenkins
Go
Buildbot

持续集成的规则:

总结规则如下:
1)经常提交代码
2)不要提交无法构建的代码
3)构建失败时,立即修复
4)写自动化测试
5)必须通过所有测试和代码审查
6)执行私有构建
7)避免迁出无法构建的代码

遵循以上规则是为了提高CI持续集成成功率,及时修复build

参考文献:
Martin Fowler的Continuous Integration
持续集成是什么?
让你的CI跑起来
持续集成工具的作用

使用Markdown编辑器写博客

本博客非原创,,转自CSDN官方编辑器提示,用来帮组小伙伴使用markdown写博客

正文如下:

本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦:

  • Markdown和扩展Markdown简洁的语法
  • 代码块高亮
  • 图片链接和图片上传
  • LaTex数学公式
  • UML序列图和流程图
  • 离线写博客
  • 导入导出Markdown文件
  • 丰富的快捷键

快捷键

  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y

Markdown及扩展

Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的HTML页面。 —— [ 维基百科 ]

使用简单的符号标识不同的标题,将某些文字标记为粗体或者斜体,创建一个链接等,详细语法参考帮助?。

本编辑器支持 Markdown Extra ,  扩展了很多好用的功能。具体请参考Github.

表格

Markdown Extra 表格语法:

项目 价格
Computer $1600
Phone $12
Pipe $1

可以使用冒号来定义对齐方式:

项目 价格 数量
Computer 1600 元 5
Phone 12 元 12
Pipe 1 元 234

定义列表

Markdown Extra 定义列表语法:
项目1
项目2
: 定义 A
: 定义 B

项目3
: 定义 C

: 定义 D

> 定义D内容

代码块

代码块语法遵循标准markdown代码,例如:

1
2
3
4
5
6
7
8
9
10
@requires_authorization
def somefunc(param1='', param2=0):
'''A docstring'''
if param1 > param2: # interesting
print 'Greater'
return (param2 - param1 + 1) or None
class SomeClass:
pass
>>> message = '''interpreter
... prompt'''

脚注

生成一个脚注[^footnote].
[^footnote]: 这里是 脚注内容.

目录

[TOC]来生成目录:

[TOC]

数学公式

使用MathJax渲染LaTex 数学公式,详见math.stackexchange.com.

  • 行内公式,数学公式为:$\Gamma(n) = (n-1)!\quad\forall n\in\mathbb N$。
  • 块级公式:

$$ x = \dfrac{-b \pm \sqrt{b^2 - 4ac}}{2a} $$

更多LaTex语法请参考 这儿.

UML 图:

可以渲染序列图:

1
2
3
张三->李四: 嘿,小四儿, 写博客了没?
Note right of 李四: 李四愣了一下,说:
李四-->张三: 忙得吐血,哪有时间写。

或者流程图:

1
2
3
4
5
6
7
8
st=>start: 开始
e=>end: 结束
op=>operation: 我的操作
cond=>condition: 确认?
st->op->cond
cond(yes)->e
cond(no)->op
  • 关于 序列图 语法,参考 这儿,
  • 关于 流程图 语法,参考 这儿.

离线写博客

即使用户在没有网络的情况下,也可以通过本编辑器离线写博客(直接在曾经使用过的浏览器中输入write.blog.csdn.net/mdeditor即可。Markdown编辑器使用浏览器离线存储将内容保存在本地。

用户写博客的过程中,内容实时保存在浏览器缓存中,在用户关闭浏览器或者其它异常情况下,内容不会丢失。用户再次打开浏览器时,会显示上次用户正在编辑的没有发表的内容。

博客发表后,本地缓存将被删除。 

用户可以选择 把正在写的博客保存到服务器草稿箱,即使换浏览器或者清除缓存,内容也不会丢失。

注意:虽然浏览器存储大部分时候都比较可靠,但为了您的数据安全,在联网后,请务必及时发表或者保存到服务器草稿箱

浏览器兼容

  1. 目前,本编辑器对Chrome浏览器支持最为完整。建议大家使用较新版本的Chrome。
  2. IE9以下不支持
  3. IE9,10,11存在以下问题
    1. 不支持离线功能
    2. IE9不支持文件导入导出
    3. IE10不支持拖拽文件导入

Angular Order And Filter

排序

angular 排序可以使用orderBy标签,它支持一个排序函数或简单地指定一个属性名进行排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# HTML5
<div ng-controller="TestCtrl">
根据age正排序
{{ data | orderBy: 'age' }} <br/>
根据age倒排序
{{ data | orderBy: '-age' }} <br/>
根据age正排序,取前2个
{{ data | orderBy: '-age' | limitTo: 2 }} <br/>
根据age倒排序,name正排序
{{ data | orderBy: ['-age', 'name'] }} <br/>
</div>
# JS 给data的值
$scope.data = [{name: 'B', age: 4},{name: 'A', age: 1},{name: 'D', age: 3},{name: 'C', age: 3}];

{ {orderBy_expression | orderBy : expression : reverse : comparator} }
orderBy_expression:数组
expression:一个String或者是一个function,用来比较的基准
reverse:反转
comparator:比较器

可以使用ng-repeat遍历,以表格形式显示

1
2
3
4
5
<tr ng-repeat="friend in friends | orderBy:['-age', 'name']">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
</tr>

JS里用order

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# JS
angular.module('orderByExample', [])
.controller('ExampleController', ['$scope','orderByFilter', function($scope, orderBy) {
var friends = [
{name: 'John', phone: '555-1212', age: 10},
{name: 'Mary', phone: '555-9876', age: 19},
{name: 'Mike', phone: '555-4321', age: 21},
{name: 'Adam', phone: '555-5678', age: 35},
{name: 'Julie', phone: '555-8765', age: 29}
];
$scope.friends = orderBy(friends, 'age', $scope.reverse);
}
# HTML5
<tr ng-repeat="friend in friends">

类似自定义的比较function即comparator等
更多内容见Angular官方文档

过滤

可以非常方便的对表格进行过滤
格式如下:
{ { filter_expression | filter : expression : comparator : anyPropertyKey} }
使用方法:

1
{{ friends | filter: 'J' }}

即对friends数组进行过滤,找到里面包含J字样的所有值。

使用表格:

1
2
3
4
5
6
7
8
<label>Search: <input ng-model="searchText"></label>
<table id="searchTextResults">
<tr><th>Name</th><th>Phone</th></tr>
<tr ng-repeat="friend in friends | filter:searchText">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
</tr>
</table>

即根据输入框的值searchText过滤friends数组的内容,并且以表格的形式显示。

更多过滤条件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<label>Any: <input ng-model="search.$"></label> <br>
<label>Name only <input ng-model="search.name"></label><br>
<label>Phone only <input ng-model="search.phone"></label><br>
<label>Equality <input type="checkbox" ng-model="strict"></label><br>
<table id="searchObjResults">
<tr>
<th>Name</th>
<th>Phone</th>
</tr>
<tr ng-repeat="friendObj in friends | filter:search:strict">
<td>{{friendObj.name}}</td>
<td>{{friendObj.phone}}</td>
</tr>
</table>

strict表示严格筛选,只有字段与搜索内容完全一致才显示。
search是筛选条件,这里可以全部一起筛选,或者只根据姓名或者电话进行筛选。

筛选条件不仅可以是字段名,还可以是自定义的函数
使用方法:

1
2
3
4
5
6
# HTML5
使用函数过滤,年龄大与19的:{{ friends | filter: f }} <br />
# JS
$scope.f = function(e){
return e.age > 19;
}

更多filter内容见angular官方文档

例子代码:
Github简单例子
Github OrderBy例子
Github filter例子

Angular Form Input Type

Form 表单中有很多元素,最普遍的Input,CheckBox,Radio,Select等等。Angular的Form有什么特殊之处呢?

Input

Input的属性有:
name 名字
type 类型(HTML5里有的类型: number,url,email)
ng-model 绑定的数据
required/ng-required 是否必填
ng-minlength 最小长度
ng-maxlength 最大长度
ng-pattern 匹配模式
ng-change 值变化时的回调

例子(输入长度5-15的起始为abc的内容):

1
<input type="text" name="a" required ng-model="a" required ng-minlength=5 ng-maxlength=15 ng-pattern="/abc/"/>

Checkbox

Checkbox只有两种值,选中和不选中。

使用方法:

1
2
3
4
5
6
7
# HTML5:
<input type="checkbox" name="checkbox" ng-model="checkbox_value" ng-true-value="AA" ng-false-value="BB"/>
<span>{{ checkbox_value }}</span>
# JS:
$scope.checkbox_value = 'AA'; #controller中的初始化值会关系到控件状态(双向绑定)

Radio

与checkbox的区别,一个radio只有一个值

1
2
3
<input type="radio" name="radio_test" ng-model="radio_test" value="AA"/>AA
<input type="radio" name="radio_test" ng-model="radio_test" value="BB"/>BB<br>
radio选中的值为:<span>{{ radio_test }}</span>

Textarea

与Input类似,但是可以拉伸

Select

使用ng-options遍历数组

x for x in 数组名(普通数组)

1
2
3
4
5
<div ng-init="o=[0,1,2,3]; a=o[1];">
<select ng-model="select_test" ng-options="x for x in o" ng-change="show()">
<option value="">可以加这个空值</option>
</select>select选中的值为: {{ select_test }}
</div>

x.name for x in 数组名(对象数组,有key,value)

1
2
3
4
<div ng-init="o2=[{name: 'AA'}, {name: 'BB'}]; a=o2[1];">
<select ng-model="select_test2" ng-options="x.name for x in o2">
</select>select选中的值为: {{ select_test2 }}
</div>

x.v as x.name for x in 数组名(选择框显示的是name的值,但选中的value值是v的值)

1
2
3
4
<div ng-init="o3=[{name: 'AA', v: '00'}, {name: 'BB', v: '11'}]; a=o3[1].v;">
<select ng-model="select_test3" ng-options="x.v as x.name for x in o3">
</select>select选中的值为: {{ select_test3 }}
</div>

x.name group by x.g for x in 数组名(根据g的值来分组)

1
2
3
4
<div ng-init="o4=[{name: 'AA', g: '00'},{name: 'BB', g: '11'},{name: 'CC', g: '00'}]; select_test4=o4[1];">
<select ng-model="select_test4" ng-options="x.name group by x.g for x in o4">
</select>select选中的值为: name值是{{ select_test4.name }};value是{{ select_test4.g }}
</div>

x.v as x.name group by x.g for x in 数组名(分组了还分别指定显示与值的,根据g分组,v的值是value值,name值是显示的内容)

1
2
3
4
<div ng-init="o5=[{name: 'AA', g: '00', v: '='}, {name: 'BB', g: '11', v: '+'},{name: 'CC', g: '00', v: '!'}]; select_test5=o5[1].v;">
<select ng-model="select_test5" ng-options="x.v as x.name group by x.g for x in o5">
</select>select选中的值为: {{ select_test5 }}
</div>

v.v as v.name group by v.g for (k, v) in 对象名(o6是一个对象,对象中有两个(key:value)对,可以取对象的值来遍历)

1
2
3
4
5
6
7
8
9
<div ng-init="o6={a: {name: 'AA', v: '00', g: '=='},b: {name: 'BB', v: '11', g: '=='}}; select_test6=o6.a.v;">
参数是对象<br>
显示对象的值里的v的值<br>
<select ng-model="select_test6" ng-options="v.v as v.name group by v.g for (k, v) in o6">
</select>select选中的值为: {{ select_test6 }}、
显示对象的名字<br>
<select ng-model="select_test7" ng-options="k for (k, v) in o6">
</select>select选中的值为: {{ select_test7 }}
</div>

Github参考代码

Angular Form Property And Class

好好学习,天天向上!

form 的相关方法要生效,必须为 form 标签指定 name 和 ng-controller,并且每个控件都要绑定一个变量。
form 和控件的名字,即是 $scope 中的相关实例的引用变量名。

Form对象属性

$pristine 表单是否未被动过
$dirty 表单是否被动过
$valid 表单是否验证通过
$invalid 表单是否验证失败
$error 表单的验证错误( key是失败信息,像required,minlength…… value是对应的字段实例列表。这里的失败信息是按序列取的一个)

使用方法:

1
2
3
4
<form name="test_form" ng-controller="TestCtrl">
<input type="text" name="a" required ng-model="a" />
<span>{{ test_form.$valid }}</span>
</form>

Form标签特定的class属性

除去对象的方法与属性, form 这个标签本身有一些class可以使用:
ng-valid 当表单验证通过时的设置
ng-invalid 当表单验证失败时的设置
ng-pristine 表单的未被动之前拥有
ng-dirty 表单被动过之后拥有

使用方法:

1
2
3
4
5
6
input.ng-invalid {
border: 1px solid red;
}
input.ng-valid {
border: 1px solid green;
}

加上两种class的css,input边框在验证通过的时候是绿色,不通过则是红色。

Github参考代码

angular官方文档

印度之旅(二)

来到一个国家,不去体验当地的风土人情,就感觉就缺了点什么。所以在印度为数不多的空闲时间里,还是和小伙伴们组队去了一些地方。

孟买的trip

在我们的计划中,只有第一个周的周末是free time,所以我们就想蹭着这个机会去印度的孟买玩一圈。
提前两三天的时候,在和美国同事聊天时发现她们也有意愿去孟买,所以立马表明了我们的心意。理所当然的,本来由中国人组成的团队扩张到了全球化的团队。

说起来,在这个过程中确实体现了美国同事的快速行动力,他们联系好了车(公司的班车),也提前预约了酒店,所以对他们来说就显得比较的享受。而我们确实因为某些原因使得我们没有那么高效。
例如,我们并不知道国外的酒店是必须网上预约后才能Check in的,因为中国的酒店你去了有房间就可以入住;在很早的时候,我们也无法确认最后晚上入住的人员;还有天气的原因的等等。

但是不论我们耽搁了多久,我们还是自己解决了住宿和吃饭的问题。

在孟买,人人都说这是印度的旅游大城市,它靠近海边(虽然海是灰色的),也有很多小摊售卖印度特色的东西,还有遗留的英式建筑。

印度人好像很喜欢装饰品,路边有超级多的卖金闪闪的项链、耳环、手链、脚链……

印度之旅(一)

难得的一个机会,让我来到了印度这个国度,在这里发生了许许多多的事,我觉得这会是一个毕生难忘的经历。

印度的幻想

关于印度,真的是不同人有不同的concern。
有人说:印度啊……好热的,上次新闻不是还说上50多度了吗,你去一定晒成黑炭
我:我读书少,你别骗我(°__°)
有人说:印度啊……好乱的,你还是别出门了
我:不出门,我去印度当宅女吗
有人说:印度啊……妹子很漂亮,身材棒的不要不要的
我:真的么(☆__☆)

结果,真正的印度,也只有去了,才知道真相是什么。

作为一个小白,再经历千辛万苦顺利上飞机,北京顺利会师,紧跟部队不放松后,终于平平安安的到达了印度。

一出机场,就觉得你TM的逗我呢!
这么凉爽的天气,说好的50多度高温呢!带了一堆夏天的”薄”衣服,要不是还有件外套,天天冻的起鸡皮
还有哪个跟我说遍地漂亮妹子的,还有一个一个包的如此严实,您老咋看出的身材

所以,到达之前,一定不要脑补太多

印度的语言

在印度,有很多很多语言,而不是我想的英语和单一的印度语。
在印度,小孩子是从小学英语的,他们还有很多电视也是英文的,路边的牌子上也有英文,所以我觉得英语应该是他们的第二语言。就像中国的,每个人都会讲自己的方言和普通话一样。
在中国,不同地方的人的普通话都有不一样的口音在。所以,你懂的,在印度,他们的英语也带有他们独特的口音,这对我来说简直就是一个灾难,英语都还有点吃力,更不用说带着口音的英语。

基本上,在印度小伙伴说话的时候,我都是一脸蒙逼。
记得很多公司的小伙伴告诉我,要做一个诚实的孩子。To be honest……
是的,要诚实,懂就是懂,不懂就是不懂,所以快看一看我这个very confuse的脸(・ω・)ノ

感觉在印度,最有用的就是肢体语言了,表情和动作,可以提供很多信息,所以当我们对着一个印度人点菜的时候……
印度人:????//????(他们说的话)
我:Em……(说的是啥,看动作好像是欢迎,算了,还是不说话,没听懂,坐下)
印度人很自觉的上了菜单。
我:Em……(全英文菜单,宝宝看不懂,拜拜……哎!等等,咱有图,嗯~这个不错)
我:This(手点),One

最后,终于吃到饭了,至于味道如何,看运气了……

本站总访问量 次, 访客数 人次, 本文总阅读量
靡不有初,<br><br>鲜克有终。<br><br>不断努力,一步一步往前走,做最好的自己