集成测试

持续集成

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

Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括:
1、持续的软件版本发布/测试项目。
2、监控外部调用执行的工作。

Jenkins使用极低的代价能部署一个软件,自动化进行项目构建,项目测试,静态扫描,上传构建,远程备份,发布。很多时候只需要点击立即构建,就进行了项目的部署操作。
它还提供权限管理,可以让不同的人员负责各自的项目建构。多项目构建,可以一次性完成多个项目的构建。

官方地址:https://jenkins.io/
docker:https://hub.docker.com/r/jenkins/jenkins/

Jenkins的原理,如果在新建的时候指定了Maven项目和代码的Git地址,Jenkins首先会通过Git将代码clone到本地,然后执行在Build中指定的pom.xml文件和指定的命令。

https://blog.csdn.net/bntX2jSQfEHy7/article/details/78743664

Jenkins 启动一直显示 Jenkins正在启动,请稍后…,深度修改配置中的访问的网站地址。
https://blog.csdn.net/heatdeath/article/details/79733611

对于自动安装失败的插件,可以在错误中找到hpi文件,通过手动下载然后在高级页面中上传插件的方式安装。

配置Publish Over SSH

在“系统设置”中配置“Publish Over SSH”。ssh的配置可使用密码,此时Passphrase中要填写应用服务器root等账号的密码。ssh的配置也可以使用密钥,使jenkins服务器可免密码直接登陆应用服务器。在配置密钥之前要先配置好jenkins服务器和应用服务器的密钥认证。在jenkins服务器上使用ssh-keygen -t rsa命令生成密钥对。在docker部署的jenkins/jenkins:lts中成功生成信息如下:

Your identification has been saved in /var/jenkins_home/.ssh/id_rsa.
Your public key has been saved in /var/jenkins_home/.ssh/id_rsa.pub.

将jenkins服务器的公钥id_rsa.pub中的内容复制到应用服务器/root/.ssh/authorized_keys文件中,在应用服务器上重启ssh服务service sshd restart。
解释两个不大明确的配置项:
Passphrase:生成rsa密钥时的密码。
Path to key:jenkins服务器上私钥文件的路径。
配置完成后可点击“Test Configuration”测试到目标主机的连接,出现”success“则成功连接。
https://www.cnblogs.com/hanxiaohui/p/8796025.html
https://www.jianshu.com/p/0d805ed204e6

全文检索

全文检索是将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
这部分从非结构化数据中提取出然后重新组织的信息,我们称之索引。这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。

Lucene是apache下的一个开源的全文检索引擎工具包(类库)。它的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。Lucene提供了完整的查询引擎和索引引擎,部分文本分析引擎。

更新依据的字段只能是字符串类型,StringField。

Document doc=new Document();
doc.add(new StringField("id","abcd",Field.Store.YES));
indexWriter.updateDocument(new Term("id","abcd"),doc);

Field.Store.YES或者NO是用来决定分词前的原内容是否存储。

lucene一个field多个条件查询
https://blog.csdn.net/guiyecheng/article/details/56484049

用lucene实现在一个(或者多个)字段中查找多个关键字
https://www.cnblogs.com/xudong-bupt/archive/2013/05/08/3065297.html

Elastic Search 概述(一)
https://blog.csdn.net/yezonggang/article/details/80064394

Elasticsearch的不足
http://dockone.io/article/3655

Docker Compose

docker-compose

docker-compose是Docker官方编排工具,用来管理和运行Docker容器,负责实现对Docker容器集群的快速编排。使用一个 Dockerfile 模板文件,可以很方便的定义一个单独的应用容器,而Compose则可以方便的实现需要多个容器相互配合来完成某项任务的情况。
Docker Compose将所管理的容器分为三层,工程(project),服务(service)以及容器(contaienr)。Docker Compose运行的目录下的所有文件(docker-compose.yml、extends文件或环境变量文件等)组成一个工程,默认名称为当前目录名。一个工程当中可包含多个服务,一个服务当中可包括多个容器实例。Docker Compose并没有解决负载均衡的问题,需要借助其他工具实现服务发现及负载均衡。
Compose 通过一个单独的 docker-compose.yml 模板文件(YAML格式)来定义一组相关联的应用容器为一个项目 (project)。
Compose 中有两个重要的概念:
服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器 实例。
项目(project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。
Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。

Docker Compose是一个部署多个容器的简单必要的工具,使用一条简单的命令部署多个容器,简化了多容器的部署过程,使多容器移植变得简单可控。从其Roadmap可以看出,Docker Compose的目标是做一个生产环境可用的工具,包括服务回滚,多环境支持(dev/test/staging/prod),支持在线服务部署升级,防止服务中断并且监控服务使其始终运行在正确的状态。Roadmap中的另一个目标是更好的与Docker Swarm集成,目前版本存在的主要问题是无法保证处于多个主机的容器间正常通信因为目前不支持跨主机间容器通信。另一个问题是在Docker Compose中定义构建的镜像只存在在一台Docker Swarm主机上,无法做到多主机共享,因此目前需要手动构建镜像并上传到一个镜像仓库使多个Docker Swarm主机可以访问并下载镜像。相信随着Docker Compose的完善,其必将取代docker run成为开发者启动docker容器的首选。

安装 Docker Compose
https://docs.docker.com/compose/install/

https://blog.csdn.net/chengqiuming/article/details/80957521

Docker服务器端用Nginx作为反向代理并添加SSL证书(阿里云免费DV证书)
https://www.cnblogs.com/wushangjue/p/7810339.html
http://www.mamicode.com/info-detail-1703824.html
http://blog.51cto.com/11962757/2086760
http://www.lixiangfeng.com/blog/article/content/8595503
https://www.jianshu.com/p/2217cfed29d7
可能冒号后需要加个空格,不然在执行 docker-compose up -d后报错ERROR: yaml.scanner.ScannerError: mapping values are not allowed here。
创建 docker-compose.yml 文件,然后在当前目录下执行命令 docker-compose up -d 来启动各个服务。

version: "2"
services:
  php-fpm1:
    image: bitnami/php-fpm
    container_name: php-fpm1
    restart: always
    links:
      - mysql1:mysql-alias
    volumes:
      - /alidata/docker_work/www:/host/www
  nginx1:
    image: nginx
    container_name: nginx1
    restart: always
    ports:
      - 81:80
      - 444:443
    volumes:
      - /alidata/docker_work/nginx/conf:/etc/nginx/conf.d
      - /alidata/docker_work:/host
    links:
      - php-fpm1:php-fpm-alias
  phpMyAdmin1:
    image: phpmyadmin/phpmyadmin:4.8
    container_name: phpMyAdmin1
    restart: always
    ports:
      - 8085:80
    environment:
      - PMA_HOSTS=172.19.0.10,172.19.0.9
      - PMA_PORTS=3306,3306
      - PMA_VERBOSES=master,slave
  hksmart-inout:
    image: node:6.15
    container_name: hksmart-inout
    restart: always
    command:
      - /bin/sh
      - -c
      - |
        cd /hksmart/hksmart-inout
        npm install
        node inout_server.js
    volumes:
      - /alidata/docker_work/node/hksmart/hksmart_inout:/hksmart/hksmart-inout

注意在此环境下的Php连接mysql,需要使用mysqli_connect。
phpmyadmin的PMA_PORTS中使用的是docker容器内部的端口。

docker-machine

VirtualBox和Docker的区别

VirtualBox和Docker的区别,一句话总结就是VirtualBox虚拟化硬件,Docker虚拟化操作系统。
VirtualBox,是创建硬件虚拟化的软件。通常情况下,一个操作系统运行在硬件上,其中硬件和操作系统之间的通信是通过移动数据到内存地址,然后发出指令来通知可使用该数据的硬件(或者是数据在被读取时)。 在VirtualBox(或其它虚拟机)设置的环境中,那些内存地址实际上是虚拟机软件自身的内存区域,并且那些指令是由虚拟机而不是直接由底层的CPU解释的。实际结果是,你在VirtualBox中运行一个操作系统,对于这个操作系统来说,VirtualBox程序看起来像一台完整计算机,硬件以及所有配件都有。实际上它不知道自己是在另一个程序中运行的。

Docker,则是不进行硬件的虚拟化。相反,它的作用是创建一个文件系统,使其看起来像一个普通的Linux文件系统,并且运行应用程序在一个所有文件和资源都在文件系统内的锁定环境中。事实上,该应用程序的容器并不模仿任何硬件,应用程序仍然在硬件上运行,它只是隔离了应用程序并允许您可以运行该应用程序跟特定的并且完全不是主机操作系统的软件和第三方库合作。这意味着,在启动或停止Docker应用程序时几乎没有开销,因为它们不需要预先分配的内存和磁盘空间等等。因此Docker容器很容易设置或者拆除。此外,容器在假装需要系统中各种硬件组件上运行软件的时候并不浪费任何开销 – 它是直接使用硬件的。

yum安装VirtualBox
配置yum源:
vim /etc/yum.repos.d/virtualbox.repo
输入

[virtualbox]
name=Oracle Linux / RHEL / CentOS-$releasever / $basearch - VirtualBox
baseurl=http://download.virtualbox.org/virtualbox/rpm/el/$releasever/$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://www.virtualbox.org/download/oracle_vbox.asc

然后用yum直接安装:
yum install VirtualBox-5.2

CentOS7下minikube start后VirtualBox执行报错
https://blog.csdn.net/jiekou0376/article/details/80454808

[root@openshift ~]# docker-machine create –driver virtualbox virtualbox1
Running pre-create checks…
Error with pre-create check: “This computer doesn’t have VT-X/AMD-v enabled. Enabling it in the BIOS is mandatory”

Docker Swarm

Docker Swarm 和 Docker Compose 都是 Docker 官方容器编排项目,不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署 Docker Swarm 更加适合。

【Docker】 Swarm简单介绍
https://www.cnblogs.com/franknihao/p/8490416.html

Swarm就是一组运行docker的机器,并联合成为一个集群。当启动Swarm集群之后,docker命令会通过Swarm manager执行在整个集群之上。Swarm集群的机器可以是物理机,也可以是虚拟机,当加入Swarm集群之后,被称为nodes。
Swarm managers有两种不同的方式运行container:第一种emptiest node,尽量使用少的机器部署容器;第二种global,确保每一台机器上都会运行一个容器的实例。可以在docker-compose.yml中指定运行的模式。
Swarm managers是集群的核心控制节点,它负责执行命令,授权新机器加入集群。Worker节点只负责提供资源。
docker可以很方便的切换为 swarm mode,切换的命令是docker swarm init,一旦切换为 swarm mode后,当前的机器角色就变为Swarm managers。

NTP

SNTP是简单网络时间协议(Simple Network Time protocol)的简称,它是目前Internet网上实现时间同步的一种重要工程化方法。
SNTP协议采用客户/服务器工作方式,服务器通过接收GPS信号或自带的原子钟作为系统的时间基准,客户机通过定期访问服务器提供的时间服务获得准确的时间信息,并调整自己的系统时钟,达到网络时间同步的目的。客户和服务器通讯采用UDP协议,端口为123。

验证ntp服务:ntpq -p
查看当前时间:date -R

查找当前地区最适合的时间服务器:打开网站 http://www.pool.ntp.org/zone/asia,会在页面上部推荐一组最合适的同步服务器。在配置ntp服务时可以把它们复制粘贴到etc/ntp.conf中。

对时请求时设置超时时间在1秒内,超时即对时不成功,保证时间精度。
https://blog.csdn.net/hexiangqwqwqw/article/details/49801573
CentOS下NTP时间服务器搭建
http://blog.51cto.com/superpcm/2089888
Centos7配置ntp时间服务器
https://blog.csdn.net/zzy5066/article/details/79036674
docker 搭建ntp服务器
https://www.cnblogs.com/liubin0509/p/6282858.html

java实现NTP客户端

添加依赖commons-net

<!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.6</version>
</dependency>

获取时间

String getDateTime(){
        try {
            NTPUDPClient timeClient = new NTPUDPClient();
            InetAddress timeServerAddress = InetAddress.getByName("cn.pool.ntp.org");
            TimeInfo timeInfo = timeClient.getTime(timeServerAddress);
            TimeStamp timeStamp = timeInfo.getMessage().getTransmitTimeStamp();
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return dateFormat.format(timeStamp.getDate());
        } catch (UnknownHostException e) {
            e.printStackTrace();
            System.out.println("与ntp服务器同步时间错误!");
            return dateFormat.format(new Date());
        } catch (IOException e) {
            System.out.println("与ntp服务器同步时间错误!");
            return dateFormat.format(new Date());
        }
    }

Tomcat

部署tomcat

到http://tomcat.apache.org/下载tomcat,下载后解压到数据盘,执行bin/startup.sh来启动tomcat。注意设置startup.sh和catalina.sh的可执行权限。

./startup.sh
./shutdown.sh

shutdown后要等一会完全关闭后再重新启动。

遇到了tomcat异常挂掉的问题

有权限问题
java.util.logging.ErrorManager: 4
java.io.FileNotFoundException: /usr/local/tomcat/logs/catalina.2017-06-11.log (Permission denied)
有内存不够的问题
[root@VM_5_53_centos logs]# service tomcat restart
Stoping Tomcat
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/java/jdk1.8.0_92
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000eb550000, 178978816, 0) failed; error=’Cannot allocate memory’ (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 178978816 bytes for committing reserved memory.
# An error report file with more information is saved as:
# //hs_err_pid14383.log
waiting for processes to exit

设置并发连接数

server.xml中在配置中,和连接数相关的参数有:
minProcessors:最小空闲连接线程数,用于提高系统处理性能,默认值为10
maxProcessors:最大连接线程数,即:并发处理的最大请求数,默认值为75
acceptCount:允许的最大连接数,应大于等于maxProcessors,默认值为100
enableLookups:是否反查域名,取值为:true或false。为了提高处理能力,应设置为false
connectionTimeout:网络连接超时,单位:毫秒。设置为0表示永不超时,但这样设置有隐患的。通常可设置为30000毫秒。
其中和最大连接数相关的参数为maxProcessors和acceptCount。如果要加大并发连接数,应同时加大这两个参数。
web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。

设置内存占用

tomcat默认可以使用的内存为128MB,在较大型的应用项目中是不够的。
Unix下,在文件{tomcat_home}/bin/catalina.sh的前面,例如增加如下设置:JAVA_OPTS=’-Xms256m -Xmx512m’,表示初始化内存为256MB,可以使用的最大内存为512MB。

对虚拟路径配置二级域名

在tomcat/conf/server.xml中增加一个Host节点,把name=”localhost”修改为域名,如下:

<Host name="domain2.brogrammer.cn" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="ReadAdmin" reloadable="false"/>
</Host>

Eclipse中配置J2EE Web module的服务容器

Eclipse是在 “服务偏好/Server/Runtime Environments” 中添加。
注意开发中和生产中要使用同一个Tomcat版本,因为编译可能要使用servlet-api.jar,要保证编译和运行版本一致,它存在于tomcat/lib中。

Tomcat配置https

1.将证书.jks文件放到tomcat/conf目录下
2.编辑conf/server.xml文件,在http和ajp节点中增加redirectPort
<Connector port=”80″ protocol=”HTTP/1.1″ connectionTimeout=”20000″ redirectPort=”443″ />
<Connector port=”8009″ protocol=”AJP/1.3″ redirectPort=”443″ />
3.编辑conf/server.xml文件,增加https节点
<Connector port=”443″ protocol=”org.apache.coyote.http11.Http11NioProtocol” maxThreads=”150″ SSLEnabled=”true”>
<SSLHostConfig>
<Certificate certificateKeystoreFile=”conf/ xxx.jks” certificateKeyAlias=”www.abc.com” certificateKeystorePassword=”” type=”RSA” />
</SSLHostConfig>
</Connector>

临时目录问题

Caused by: java.io.IOException: The temporary upload location [/tmp/tomcat.**/work/Tomcat/localhost/ROOT] is not valid
原因分析:临时文件夹无效,系统可能清除了临时目录。

解决方案一:
重启服务,临时方案:会重新生成tomcat目录,但是生产环境不建议如此操作;

解决方案二:
1增加服务配置,自定义baseDir:
2启动时增加参数-Djava.io.tmpdir=自定义目录

解决方案三:
注入一个Bean,手动配置临时目录

/**
 * 文件上传临时路径
 */
 @Bean
 MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    factory.setLocation("/app/pttms/tmp");
    return factory.createMultipartConfig();
}

WebSocket

WebSocket

HTML5新特性之WebSocket
http://blog.csdn.net/liuhe688/article/details/50496780
在nodejs中使用websocket
https://github.com/websockets/ws

angular-websocket

angular-websocket
https://www.npmjs.com/package/angular-websocket
在angular工程中使用angular-websocket:

#index.html中  <script src="bower_components/angular-websocket/dist/angular-websocket.min.js"></script>
#app.js中 angular.module('appmodule1', ['angular-websocket'])
#controller中
app.controller('UnitsReportsCtrl', function($scope, $websocket) {
        if(!$scope.ws) {
            $scope.ws = $websocket("ws://localhost:8181");

            $scope.ws.onOpen(function (e) {
                console.log('Connection to server opened');
            });
            $scope.ws.onMessage(function (e) {
                console.log('received',e);
            });
        }
        $scope.ws.send('test11');
}

目前WebSocket可以收发消息的类型有String、Blob和ArrayBuffer,后面两个主要用于收发二进制数据的,日常开发中使用String类型就足够了,如果想要发送自定义对象,只需将其转换成JSON字符串后发送,如果客户端和服务端是以JSON形式通信,客户端收到消息后在将其转换为JavaScript对象即可。

Blob

BLOB (binary large object),二进制大对象,是一个可以存储二进制文件的容器。
XMLHttpRequest 相关的数据类型:DOMString、FormData、Blob、File、FileReader这些类型,在XMLHttpRequest Level 2背景下,Ajax可以发送任意这些类型的数据。
可以在MDN Web API 接口页面中找到它们:https://developer.mozilla.org/zh-CN/docs/Web/API

Blob数据对象
http://blog.csdn.net/charlene0824/article/details/51340238
html上面通过websocket接收二进制图片数据并显示在页面上
http://blog.csdn.net/wushuang443/article/details/65442754
js中关于Blob对象的介绍与使用
https://www.cnblogs.com/wangfajing/p/7202139.html?utm_source=itdadao&utm_medium=referral
Blob/DataURL/canvas/image的相互转换,TypeArray、ArrayBuffer、Blob、File、DataURL、canvas的相互转换
https://www.cnblogs.com/jyuf/p/7251591.html
https://www.cnblogs.com/flicat/p/5337054.html

强类型数组

常用的Array并不是真正的数组,它其实是一个从哈希表扩展的结构体,因此Array可以提供push、splice等操作,但效率低。JavaScript中真正的数组是强类型数组。
由于现在JavaScript变得需要访问原始的二进制数据,这些底层的操作需要直接访问内存,因此引入了这些强类型的数组。
ArrayBuffer
Int8Array
Int16Array
Int32Array
Uint8Array
Uint8ClampedArray
Uint16Array
Uint32Array
Float32Array
Float64Array
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects

Android6.0

6.0权限

权限分为了普通权限和需要单独申请的权限.
http://www.jianshu.com/p/a51593817825
PermissionsDispatcher
https://github.com/permissions-dispatcher/PermissionsDispatcher
在运行时请求权限
https://developer.android.com/training/permissions/requesting.html

新技术

新语言 Kotlin
Android程序是运行在Java虚拟机之上的,因此从技术上来说,可以运行在JVM之上的一切都可 用于开发Android应用。现在已经有很多可以生成JVM能够执行的字节码的语言,其中一些语言开始崭露头角并逐步流行起来,Kotlin就是其中的佼 佼者。

新存储 Realm
Android平台有很多的orm框架可以对数据作本地存储,比如ormlite、greenDao、SugarORM等等,这些orm框架基本都是基于sqlite的。今天我要介绍的这个数据库Realm,是用来替代sqlite的一种解决方案,它有一套自己的数据库存储引擎,比sqlite更轻量级,拥有更快的速度,最重要的是跨平台,目前已有Java,Objective C,Swift,React-Native,Xamarin这五种实现。

网络通信
新的网络通信框架 Volley

新框架
RXJava,
订阅发布模式Otto,RXAndroid ,RXBus ,EventBus,android.database.Observable

Android应用获取通知栏权限是否开启–以及跳转到系统设置界面–解决方案
http://blog.csdn.net/qq_22637473/article/details/53466425

AngularJS

版本:
Angular2以后官方的称呼就叫Angular,不是Angular2,也不是Angular4,而1.x版本的老版本,叫AngularJS。

学习AngularJS 1.x:
https://hairui219.gitbooks.io/learning_angular/content/zh/chapter05_1.html

ng-app指令

一个AngularJS web应用中只能出现一个ng-app指令,它相当于main方法。
有两种写法,ng-app或者ng-app=”自定义的模块”,ng-app有一个默认的模块,ng-app=“自定义的模块” 是一个使用了自定义的模块,该自定义的模块继承了那个初始的默认的模块,可以调用初始的默认的模块的方法。
HTML5规范要求所有的用户自定义属性以”data-“开头,所以data-ng-app是符合HTML5规范的写法,用HTML Validator检查代码的时候,ng-app会报错,而data-ng-app不会。

控制器——controller

控制器——controller 是一种封装,是AngularJS设计模式的一种定义。
可以通过ng-controller指令来隐式为模板创建一个控制器,也可以通过$controller服务来创建一个控制器。
控制器的用于增强作用域,包括设置好作用域对象的初始状态,以及给作用域对象增加行为。
控制器通过AngularJS的另一个设计模式——依赖注入 来使用更多服务。比如$scope。可以将$scope理解为 页面与数据的高速通道、桥梁、连接、粘合剂,也就是控制器中定义的所有东西,想要反应到页面上,就必须通过$scope。

使用ng-init向controller中传递参数

使用ng-init向controller中传递参数,不能立即获取到,是因为 “the controller is being created before the variable is added to the $scope object”

<div ng-include="'modules/units/views/view.html"
     ng-controller="UnitsViewCtrl"
     ng-init="unitId = '123'">
</div>
$scope.setUnitId=function(unitId) {
    $stateParams.id=unitId;
    getData();
}
<div ng-include="'modules/units/views/view.html'"
     ng-controller="UnitsViewCtrl"
     ng-init="setUnitId('123')">
</div>

可以使用$watch,或者在ng-init中调用函数
http://corpus.hubwiz.com/2/angularjs/18608161.html

ng-template寄宿方式

<script type="text/ng-template" id="/tpl.html">
 Content of the template.
 </script>

angular.js 中 父级和 子集 controller 之间的通讯
http://yijiebuyi.com/blog/62f8daffb5c629e85de91ca0b3942985.html

AngularJs中的directive(一)
https://segmentfault.com/a/1190000007018923

$watch监听属性变动

$watch是一个scope函数,用于监听模型变化,当模型部分发生变化时通知。$watch函数会返回一个注销监听的函数。
示例:

$scope.multiModel = [];
var destroyWatch = $scope.$watch('multiModel.length', function () {
//如果不再需要监听,则注销。
destroyWatch();
})

angularjs-dropdown-multiselect

http://ngmodules.org/modules/angularjs-dropdown-multiselect

<script src="https://cdn.bootcss.com/angularjs-dropdown-multiselect/1.11.8/angularjs-dropdown-multiselect.min.js"></script>
angular.module('hxyclient', [
    'angularjs-dropdown-multiselect'
]).....
$scope.multiModel = []; 
$scope.multiModelOptions = [{id: 1, label: "text1"}];
<div ng-dropdown-multiselect="" style="float:left;" extra-settings="{ scrollableHeight: '500px', scrollable: true }"
     options="multiModelOptions" translation-texts="{buttonDefaultText:'选择属性',dynamicButtonTextSuffix:'选择属性',checkAll:'全选',uncheckAll:'重置'}"
     selected-model="multiModel" checkboxes="true">
</div>

ng-if中的ng-model值无效的问题

与其他指令一样,ng-if指令也会创建一个子级作用域,在ng-if中每个包含的元素都拥有自己的作用域,相对于控制器作用域来说,这个作用域属于一个子级作用域,所以要绑定控制器中的变量值必须添加$parent标识。

gulp编译后select控件缺失请选择项

查看编译后的html文件,发现option内容变成了

<option value>-- 选择所属工程 --</option>

在源码中把value的值由””(空白)修改为” “(空格)解决了问题。对取值做trim可使编译前的代码恢复正常工作。

<select ng-model="collector.projectId" ng-options="item.id as item.name for item in projects" required>
  <option value=" ">-- 选择所属工程 --</option>
</select>

指令

scope中不同类型配置,在html中传值的格式不同。
@ 直接传值 字符串单向绑定,
= 传引用,模型双向绑定,
& 方法绑定
bool值需要设置为=,如果出现值总是传不进去,尝试更换scope中的参数名。

app.directive('unitParaGroup', function() {
    return {
        restrict: 'E',
        templateUrl: 'modules/units/components/units.paraGroup.html',
        scope : {
            title : '@',
            unitData: '=',
            attributes:'=',
            column : '@',
        },
    };
})
<unit-para-group title="机组参数设定" attributes="analogSettingAttrs" unit-data="unitLastestData" column="{{unitParaGroupColumn}}" ng-if="!hideSettingGroup"></unit-para-group>

在angular1.5的版本之前,都是以directive作为组件化的形式,而directive本身是一个指令,而并非是一个组件,所以它并不能很好的承担组件这一个职责,所以google在angular1.5的版本中推出了component组件。

数据共享

在多个controller中共享数据的方式

  • 使用$rootScope
  • 使用service
  • 通过$scope的事件传播

要注意如果需要共享的数据是网络获取到的,并且多个controller同时发起请求,为了做到只需要一个实际请求即可,需要做请求状态判断处理。
在多个AngularJS controller之间共享数据
http://blog.51cto.com/xitongjiagoushi/1684429

双花括号:是angular内置的一种混合(Markup)指令,它会将表达式绑定到元素。
局部模板:模板片段
数据绑定是模型与视图间的自动同步,视图是模型的投影,当模型或视图改变时,它们会互相反映这种改变。

grunt或gulp Unknown provider: aProvider

多是因为使用了隐匿依赖,在代码压缩后会失效。解决办法,编写所有service、directive用数组注入。
http://tobato.iteye.com/blog/2116307

React Native

React Native

React Native 中文网
http://reactnative.cn/
https://facebook.github.io/react-native/
官方文档
https://facebook.github.io/react-native/docs/getting-started.html
http://www.jianshu.com/p/a4d16de07350
http://www.jianshu.com/p/7a4899bde137
http://www.reactnative.com/
react-navigation使用技巧
http://www.jianshu.com/p/2f575cc35780

To run your app on iOS:
   cd /Users/hycx/x_workspace/AwesomeProject
   react-native run-ios
   - or -
   Open ios/AwesomeProject.xcodeproj in Xcode
   Hit the Run button
To run your app on Android:
   cd /Users/hycx/x_workspace/AwesomeProject
   Have an Android emulator running (quickest way to get started), or a device connected
   react-native run-android

目前来说用rn对我来说最大的好处应该是同时开发android和ios,大部分代码通用,而且可以使用 code-push 来热更新。
https://www.zhihu.com/question/36722811

在Android手机上运行React-native项目时报错:unable to load script from assets ‘index.android bundle’ ,make sure your bundle is packaged correctly or youu’re runing a packager server

解决方案:
第一步:在 android/app/src/main 目录下创建一个 assets空文件夹
第二步:执行 下面这段命令

react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/  

会发现 assets文件夹下多出两个文件
第三步:重新run程序。

总结:
index.android.bundle是用来调用原生控件的js脚本,每次改变了 index.android.js,都需要使用上面的代码片段更新index.android.bundle,然后打包才可以把新的index.android.js应用上,所以当没有index.android.bundle文件时,RN是无法运行的.

React Native BLE蓝牙通信
http://blog.csdn.net/withings/article/details/71378562?locationNum=3&fps=1
https://github.com/innoveit/react-native-ble-manager

安装chrome扩展程序: React Developer Tools
react-native run-android 命令只需要在手机上还没有安装项目软件时执行,如果已经安装了,只要在手机上手动打开app即可。
react-native start
ifconfig ,查看en0中对应的ip,
打开app,摇晃手机,或者按菜单,或者长按菜单键,打开帮助菜单,在Dev Settings/Debug server host & port for device中填写ip:port。

图片
安卓中使用资源图片:
把ic_launcher.png拷贝放到drawable-hdpi中,

学习React Native必看的几个开源项目
http://www.cnblogs.com/qiangxia/p/5584622.html

编译运行f8app
需要在android studio中安装 google repository 和 google play services,升级各种更新,修改compileSdkVersion等。
https://github.com/fbsamples/f8app/issues/154
http://www.jianshu.com/p/f7cb35436f9a
http://www.jianshu.com/p/3fd0203334fe

react-navigation 简单使用
http://www.jianshu.com/p/2ce08b92cf60
https://reactnavigation.org/docs/intro/
http://www.cnblogs.com/CrazyWL/p/7283600.html

StatusBar 使用
http://blog.csdn.net/mengks1987/article/details/71127885
http://www.hangge.com/blog/cache/detail_1613.html

SectionList
If you need sticky section header support, use ListView for now.