学习React的时候,跟着教程做的一个简单的新闻站点,使用了Ant Design React组件库,适配移动和PC端,最后发布在leanCloud上。
地址: http://reactnews.leanapp.cn

最近一直在开发国网招投标项目,把我这辈子的班都加了。。。。。。

概述

一个基于Java的半自动化持久层框架。MyBatis不会为开发者自动生成SQL执行,而是需要开发人员自己写SQL,然后通过映射配置文件,将返回返回结果映射到指定的POJO。

核心配置文件mybatis-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<configuration>
<!-- 实体类的别名 -->
<typeAliases>
<typeAlias type="com.icss.mybatis.pojo.Student" alias="Student"/>
</typeAliases>
<!-- 环境管理,可以配置多个环境,默认是default="development"的环境 -->
<environments default="development">
<environment id="development">
<!-- 事务管理方式,JDBC事务 -->
<transactionManager type="JDBC" />
<!-- 数据源,type="POOLED"表示使用连接池 -->
<dataSource type="POOLED">
<property value="com.mysql.jdbc.Driver" name="driver" />
<property value="jdbc:mysql://localhost/mybatis" name="url" />
<property value="root" name="username" />
<property value="123456" name="password" />
</dataSource>
</environment>
</environments>

<!--映射文件路径,可能会有多个mapper映射 -->
<mappers>
<mapper resource="com/icss/mybatis/pojo/StudentMapper.xml"/>
</mappers>
</configuration>

实现crud基本步骤

1.创建POJO

​ 创建数据库表对应的Java类,此处省略

2.创建配置Mapper映射文件

1
2
3
<mapper namespace="people" >

</mapper>

3.在Mapper映射文件中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<mapper namespace="people" >
<resultMap id="BaseResultMap" type="com.yonyou.sg.cpu.basedoc.domain.People" >
<id column="pk_people" property="pkPeople" jdbcType="BIGINT" />
<result column="modifier" property="modifier" jdbcType="VARCHAR" />
<result column="code" property="code" jdbcType="VARCHAR" />
<result column="creationtime" property="creationtime" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="modifiedtime" property="modifiedtime" jdbcType="VARCHAR" />
<result column="creator" property="creator" jdbcType="VARCHAR" />
<result column="ts" property="ts" jdbcType="TIMESTAMP" />
<result column="dr" property="dr" jdbcType="SMALLINT" />
</resultMap>
<select id="getPeopleByPK" resultMap="BaseResultMap" parameterType="java.lang.Long">
select * from people where pk_people=#{pk}
</select>
</mapper>

配置表列与类属性映射的结果集,type属性可以使用完整pojo类名,如果定义了类别名,也可以使用类别名
不需要把所有字段都映射,可以只映射一部分,主键字段必须用id元素指定

‘#{}‘语法用于插入动态数据,数据来源于调用此语句时传入的参数,参数类型由parameterType属性决定

4.核心配置文件中,引入Mapper

1
2
3
<mappers>	
<mapper resource="com/icss/mybatis/pojo/PeopleMapper.xml"/>
</mappers>

5.读取核心配置文件,调用CRUD功能

1
2
3
4
5
private SqlSessionFactory sessionFactory;

InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

sessionFactory = new SqlSessionFactoryBuilder().build(is);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
这里执行Sql有两种方式:
1.通过namespace+statementId
public void testInsert() {

SqlSession session = sessionFactory.openSession();
Student stu = new Student("李四",Date.valueOf("1987-6-10"),"119");
session.insert("people.insert", stu);
session.commit();
session.close();
}

2.创建Dao接口,(Mapper的namespace路径必须与dao接口路径一致)
//dao接口申明
package com.icss.mybatis.dao;
import java.util.List;
import com.icss.mybatis.pojo.Student;
public interface StudentMapper {
void insert(Student stu);
void udpate(Student stu);
void delete(Integer stuId);
Student queryById(Integer stuId);
List<Student> query();
}
//执行sql
public void testInsert() {
SqlSession session = sessionFactory.openSession();
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
Student stu = new Student("钱七",Date.valueOf("1990-6-7"),"114");
studentMapper.insert(stu);
session.commit();
session.close();
}

动态SQL元素

1
2
3
4
5
6
if
choose(when,otherwise)
trim
where
set
foreach
1
2
3
4
5
6
7
8
9
10
11
12
<select id="queryByCondition" parameterType="com.icss.mybatis.pojo.Student" resultMap="BaseResultMap">
select * from student where 1=1
<if test="stuName != null and stuName != ''">
and stu_name=#{stuName}
</if>
<if test="stuBirthdate != null">
and stu_birthdate=#{stuBirthdate}
</if>
<if test="stuPhone != null and stuPhone != ''">
and stu_phone=#{stuPhone}
</if>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id="queryByCondition2" parameterType="com.icss.mybatis.pojo.Student" resultMap="BaseResultMap">
select * from student where 1=1
<choose>
<when test="stuName != null and stuName != ''">
and stu_name=#{stuName}
</when>
<when test="stuBirthdate != null">
and stu_birthdate=#{stuBirthdate}
</when>
<otherwise>
and stu_phone=#{stuPhone}
</otherwise>
</choose>
</select>

choose元素相当于java语句的if … else if …else语句
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id="queryByCondition3" parameterType="com.icss.mybatis.pojo.Student" resultMap="BaseResultMap">
select * from student
<where>
<if test="stuName != null and stuName != ''">
and stu_name=#{stuName}
</if>
<if test="stuBirthdate != null">
and stu_birthdate=#{stuBirthdate}
</if>
<if test="stuPhone != null and stuPhone != ''">
and stu_phone=#{stuPhone}
</if>
</where>
</select>

使用where元素会自动根据条件的个数增删where语句and运算符,所以不需要写where 1=1之类的语句
1
2
3
4
5
6
7
8
9
10
<!-- 动态SQL:传入Array数组 -->
<select id="queryByInArray" resultMap="BaseResultMap">
select * from student
<if test="array.length>0">
where stu_id in
<foreach collection="array" index="i" item="stuId" open="(" close=")" separator=",">
#{stuId}
</foreach>
</if>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 动态SQL:trim标签 -->
<select id="queryByCondition4" parameterType="com.icss.mybatis.pojo.Student" resultMap="BaseResultMap">
select * from student
<trim prefix="where" prefixOverrides="and|or">
<if test="stuName != null and stuName != ''">
and stu_name=#{stuName}
</if>
<if test="stuBirthdate != null">
and stu_birthdate=#{stuBirthdate}
</if>
<if test="stuPhone != null and stuPhone != ''">
or stu_phone=#{stuPhone}
</if>
</trim>
</select>
trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 动态SQL:set更新 -->
<update id="updateByCondition" parameterType="com.icss.mybatis.pojo.Student">
update student
<set>
<if test="stuName!=null and stuName!=''">
stu_name=#{stuName},
</if>
<if test="stuBirthdate!=null">
stu_birthdate=#{stuBirthdate},
</if>
<if test="stuPhone!=null and stuPhone!=''">
stu_phone=#{stuPhone}
</if>
</set>
where stu_id=#{stuId}
</update>

css扩展语言,兼容css,因此在less文件里即可使用扩展的特性也可使用标准css

定义变量

1
2
3
@color:red

#header{background-color:@color}

定义函数

1
2
3
.border-color(@color){
border-color:@color
}

使用:

1
2
3
.header{
.border-color(red)
}

混合

1
2
3
4
.border{
border-color:red;
border-top:solid 1px black;
}

其他属性集合内部使用:

1
2
3
4
#menu{
color:red;
.border;
}

嵌套

标准css写法

1
2
3
4
5
6
7
8
9
#header{
color:black;
}

#header .navigation{
font-size:12px;
}

#header .logo{
width:300px;
}

less的写法

1
2
3
4
5
6
7
8
9
#header{
color:black;
.navigation{
font-size:12px;
}
.logo{
width:300px;
}
}

运算

任何数值,颜色和变量都可以进行运算

1
2
3
@base:5%;
@filler:@base * 2;
@other:@base + @filler

作用域

less中变量的作用域,首先会在局部查找,如果没有再去父作用域查找

1
2
3
4
5
6
7
@var:red
#header{
@var:white;
#title{
color:@var;//white
}
}

导入

1
@import "library.less";

函数

less提供了许多的用于颜色转换,字符串处理,运算等的函数。

1
2
3
4
@base:0.5;
.header{
width:percentage(@base);//50%
}

Webpack 是javascript应用的模块打包器(module bundler)。可以通过配置文件分析项目的结构,找到所有依赖,资源后进行打包输出供浏览器使用。

Webpack主要有四大核心概念:

Entry

webpack打包资源的入口文件,webpack.config.js 配置文件中配置entry属性

module.exports = {
  entry: './path/to/my/entry/file.js'
};

Output

打包后的资源的存放位置,配置output属性

var path = require('path');

module.exports = {
      entry: './path/to/my/entry/file.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js'
      }
};

Loaders

通过调用外部脚本或工具,对各种格式的文件进行处理打包

test:需要被处理的文件
use:loader的名称,调用处理

var path = require('path');

const config = {
      entry: './path/to/my/entry/file.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js'
     },
      module: {
           rules: [
              {test: /\.(js|jsx)$/, use: 'babel-loader'}
        ]
      }
};

module.exports = config;

Plugins

插件是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。

const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');

const config = {
      entry: './path/to/my/entry/file.js',
     output: {
            path: path.resolve(__dirname, 'dist'),
         filename: 'my-first-webpack.bundle.js'
      },
      module: {
        rules: [
              {test: /\.(js|jsx)$/, use: 'babel-loader'}
        ]
      },
     plugins: [
        new webpack.optimize.UglifyJsPlugin(),
        new HtmlWebpackPlugin({template: './src/index.html'})
      ]
};

module.exports = config;

###使用webpack构建本地服务器
Webpack提供一个可选的本地开发服务器,这个本地服务器基于node.js构建,可以实现更改代码后浏览器自动刷新,
首先得安装组件:

npm install --save-dev webpack-dev-server

然后配置

var path = require('path');

const config = {
      entry: './path/to/my/entry/file.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js'
     },
      module: {
           rules: [
              {test: /\.(js|jsx)$/, use: 'babel-loader'}
        ]
      }

    devServer: {
            contentBase: "./public",//本地服务器所加载的页面所在的目录
            colors: true,//终端中输出结果为彩色
         historyApiFallback: true,//不跳转
         inline: true//实时刷新
      } 
};

module.exports = config;

开发过程中发现对React Native生命周期的理解还不够完整,导致渲染的时候性能出现问题,所以写了个例子观察了一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/


import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import ChildComponent from './child';
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
content:'content'
};
}

componentDidMount(){
console.log('Parent====componentDidMount')
}

render() {
console.log('Parent====render')
return (
<View style={styles.container}>
<Text style={styles.welcome}>
{this.state.content}
</Text>
<ChildComponent content={this.state.content}/>
<Text style={{margin:20}} onPress={()=>{this.onPress()}}>Press Me!</Text>
<Text style={{margin:20}} onPress={()=>{this.onPressME()}}>Press!</Text>
</View>
);

}

onPress(){
this.setState({content:'React Native Props'});
}

onPressME(){
this.setState({content:'React Native'});
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/


import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';

export default class Child extends Component {
constructor(props) {
super(props);
this.state = {
content:this.props.content
};
}

componentWillMount(){
console.log('child====componentWillMount')
}

//先调用子组件的 componentDidMount(),然后调用父组件的函数
componentDidMount(){
console.log('child====componentDidMount')
}

//1.父组件触发render后触发子组件该方法,不管属性是否改变;
//2.这里setState不会触发额外的render()
componentWillReceiveProps(nextProps){
console.log(this.props.content+'===='+'componentWillReceiveProps'+'====='+nextProps.content)
this.setState({content:'componentWillReceiveProps'});


}

shouldComponentUpdate(nextProps,nextState){
console.log('shouldComponentUpdate')
return true
}

// 这个函数调用之后,就会把 nextProps 和 nextState 分别设置到 this.props 和 this.state 中
componentWillUpdate(nextProps,nextState){
console.log('componentWillUpdate')
}

render() {
console.log('child render')
return (
<View style={styles.container}>
<Text style={styles.welcome}>
{this.props.content}
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
</View>
);

}

componentDidUpdate(prevProps,prevState){
console.log(prevProps.content+'===='+'componentDidUpdate'+'====='+this.props.content)
}
}

const styles = StyleSheet.create({
container: {

justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
第一次加载:
parent.js:28 Parent====render
child.js:24 child====componentWillMount
child.js:52 child render
child.js:29 child====componentDidMount
parent.js:24 Parent====componentDidMount

点击Press Me!:
parent.js:28 Parent====render
child.js:35 content====componentWillReceiveProps=====React Native Props
child.js:42 shouldComponentUpdate
child.js:48 componentWillUpdate
child.js:52 child render
child.js:66 content====componentDidUpdate=====React Native Props

再次点击Press Me:
parent.js:28 Parent====render
child.js:35 React Native Props====componentWillReceiveProps=====React Native Props
child.js:42 shouldComponentUpdate
child.js:48 componentWillUpdate
child.js:52 child render
child.js:66 React Native Props====componentDidUpdate=====React Native Props

点击Press!:
parent.js:28 Parent====render
child.js:35 React Native Props====componentWillReceiveProps=====React Native
child.js:42 shouldComponentUpdate
child.js:48 componentWillUpdate
child.js:52 child render
child.js:66 React Native Props====componentDidUpdate=====React Native