李续铖的博客


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

React Native 界面跳转

发表于 2016-07-17 | 分类于 APP

先放上 app.js 中的主要代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import List from './ListView';
const defaultRoute = {
component: List,
name:'List'
};
class RnDemo extends Component {
_renderScene(route, navigator) {
let Component = route.component;
return (
<Component {...route.params} navigator={navigator} />
);
}
render() {
return (
<Navigator
initialRoute={defaultRoute}
renderScene={this._renderScene}/>
);
}
}

  • 第一行是引用了一个文件,listview中就是我们打开app想要展示的第一个界面的内容,那么现在的 List 就是这个界面的组件的名字,详细后面再说,我们继续看

  • 第三行我们定义了一个对象,这个对象中有两个属性,name和component,component我们用 List 去赋值,这是个什么东西呢? 其实,这里的component也就是 List 中的class就是我们将要在下面的component中实例化的组件

  • 我们直接看17行,这是一个Navigator标签,他就是我们的导航器标签,我们看他的属性,initialRoute 是什么呢,其实这里才是设置app打开要显示的默认界面是什么,所以我们就可以把上面的 defaultRoute 放进去了

  • 19行这个就是很重要的了,reanderScene 是什么呢,我们发现给他赋值的是一个叫renderScene的方法,那我们回去看第9行。我们发现这里有两个参数route、 navigator,这又是什么鬼呢,其实route里就是我们上面传递的name和component这两个货,也就是我们将要在navigator里面push的东西,navigator是一个Navigator的对象,那我们在看函数里面,第10行,我们取出router里面的component,根据上面我们知道,这个component其实就是我们引用的ListView里面的那个class,所以下面我们可以用component生成一个标签,其实就是实例化了一个ListView里面的类,我们再来看属性,…route.params 其实就是给下一个界面传参,这个我们下面介绍。然后navigator作为props传递给了这个component,这样下一个界面就可以使用这个navigator来进行界面返回等其他操作了

下面我们看一下ListView里面的代码

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
import Detail from './Detail';
class List extends Component {
constructor(props) {
super(props);
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
var list = [];
for (var i = 0; i < 20; i++) {
list[i]='listItem'+i;
}
this.state = {
dataSource: ds.cloneWithRows(list),
};
}
itemClick(e, dataData){
this.props.navigator.push({
name: 'Detail',
component: Detail,
params: {
data: dataData
}
})
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) =>
<TouchableHighlight onPress={(event) => this.itemClick(event, rowData)} underlayColor='lightgray'>
<View style={style.tableItem} >
<View ><Image style={style.img} source={require('../imgs/img.jpg')}></Image></View>
<View ><Text style={style.title}>{rowData}</Text></View>
</View>
</TouchableHighlight >
}
/>
);
}
}
export default List;

我们就看一下主要的吧,在这里我定义了一个List的组件,并通过export暴露出去,这样在 app.js 我们就可以使用他来实例化标签了

另一个重要的地方是16行,由于这个界面是一个list列表,所以 我就定义了一个 itemClick 方法,去响应每一个item的点击
由于我们之前吧把navigator对象作为组件的属性传递下来了,所以我们这里当然就可以使用 this.props.navigator 来获取到他,并进行界面跳转操作,在这里我们 push 一个新界面 component 就是我们我们要打开的界面的组件类,然后我们其实想要让下面的界面知道我是点击那个item进入的呀,所以我想把item的内容当做参数传递下去,!!!重点来了,可以发现我这里写了一个叫 params 的对象在这个对象里面我写入了我要传递的数据,那为什么写到这里就会传递下去呢? 如果你还没忘的话,其实我们在上面已经写了

1
2
3
4
5
6
_renderScene(route, navigator) {
let Component = route.component;
return (
<Component {...route.params} navigator={navigator} />
);
}

就是这里,app.js 中我们已经设置了把路由中的params拿出来作为新组件的属性,这样我们就可以在新组件里面通过 this.props 获取了,下面我们去detail中看一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Detail extends React.Component {
constructor(props){
super(props);
this.state = {
data : this.props.data,
};
}
BackClick(){
const { navigator } = this.props;
if(navigator) {
navigator.pop();
}
}
render() {
return (
<View >
<TouchableHighlight onPress={(event) => this.BackClick(event)} underlayColor='lightgray'>
<Text>{this.state.data}</Text>
</TouchableHighlight>
</View>
);
}
}
export default Detail;

刚刚已经介绍了,在这里我们可以通过this.props去获取上一个界面传递下来的数据

我们再来看一下界面返回,第九行,其实就是获取到navigator后,如果navigator存在就pop();这样就可以成功返回上一个界面了

其实,做界面跳转还可以使用 React-Router 等,这个我们下回再介绍吧^-^

React+Redux 单界面应用

发表于 2016-07-15 | 分类于 前端

之前的项目需要做一个后端管理的web,既然要做,就挑战一下自己吧,打算使用react+redux 做一个单界面的应用。为什么要用这个组合去做呢,React我就不解释了,这是最近非常火的一个前端框架,但是他还是有一些缺点的,比如他在各组件之间的数据交互相对来说比较麻烦,而Redux的作用就是用来管理数据流,管理状态,所以选择用React和Redux结合起来做。

这里还要使用一些其他的框架,使用 react-redux 去连接React和Redux;使用 react-router 和 react-router-redux 去做前端路由;使用 redux-thunk 去支持异步action等。

下面了解一下Redux的数据流(按顺序进行):

首先触发action:action 可以理解为应用向 store 传递的数据信息(一般为用户交互信息)。在实际应用中,传递的信息可以约定一个固定的数据格式,简单形式如下

1
2
3
function getCourse(data) {
return {type: 'Get_Courses', data};
}

dispatch(action):这是一个同步的过程:执行 reducer 更新 state -> 调用 store 的监听处理函数。如果需要在 dispatch 时执行一些异步操作可以通过引入 Middleware(redux-thunk) 解决。

最后reducer 改变状态:reducer的作用就是根据现在的state和action来得到新的state,也就是说这有在这一步state树才会被改变。

下面结合我的代码去说明:(这里以获取课程信息为例)

首先是前端目录结构:

1
2
3
4
5
6
7
8
9
10
11
admin/
├── actions/ 用于存放action文件
│ └── course.js
├── components/ 能够复用的React组件
├── containers/ 界面
| └── course.js
├── reducers/ 存放reducers处理文件
| └── course.js
├── store/ 将reducer整合在一起
| └── rootStore.js
└── index.js 入口文件

action/course.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function getCourse(data) {
return {type: 'Get_Courses', data};
}
export function getCoursesAction(data) {
return dispatch=> {
fetch(`/admin/course/list?search=${data.search}&page=${data. page}`, {credentials: 'include'})
.then((response) => response.text())
.then((responseText) => {
var data = JSON.parse(responseText);
data.data = JSON.parse(data.data)
dispatch(getCourse(data))
})
.catch((error) => {
console.warn(error);
});
}
}

因为action函数是不支持异步的,所以这里将异步操作放到getCoursesAction函数里面,当异步获取成功数据之后通过dispacth调用getCourse函数将数据提交给reducer处理。


reducers/course.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var defaultFields = {
data: [],
total:0,
page:1,
count:10,
search: '',
};
export function courses(state = defaultFields, action) {
switch (action.type) {
case 'Get_Courses':
return action.data
default:
return state;
}
}

其实这里的参数action就是我们在action/course.js中返回的数据

1
return {type: 'Get_Courses', data};

所以我们通过action.type获取我们约定的操作,这里我们如果type是“Get_Courses”就会根据action里面的data更新state。


store/rootStore.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { createStore, applyMiddleware,compose ,combineReducers} from 'redux';
import {routerReducer} from 'react-router-redux';
import thunk from 'redux-thunk';
import * as course from '../reducers/course.js';
//将拆分的reducer组合起来
const reducer = combineReducers({
...course,
routing: routerReducer
});
//添加中间件
const createStoreWithMiddleware = compose(
applyMiddleware(
thunk
),
window.devToolsExtension ? window.devToolsExtension() : f => f
)(createStore)
//生成store
export default createStoreWithMiddleware(reducer)

containers/course.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mport React, { Component } from 'react';
import { connect } from 'react-redux';
class Course extends React.Component {
...
render() {
//获取到courses数据
var data = this.props.data;
return(...);
}
}
//将store中的course信息绑定到Course组件的props上
function show(state) {
return {
data: state.courses,
fields:state.fields
};
}
export default connect(show)(Course);


index.js:

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
import { createStore, applyMiddleware,compose ,combineReducers} from 'redux';
import { Provider } from 'react-redux';
import Share from './components/share.js';
import User from './containers/user.js';
import Field from './containers/field.js';
import Course from './containers/course.js';
import Section from './containers/section.js';
import Lesson from './containers/lesson.js';
import store from './store/rootStore.js';
import {routerReducer, syncHistoryWithStore } from 'react-router-redux';
import { Route, Router ,browserHistory, IndexRoute ,hashHistory } from 'react-router';
import {createHistory } from 'history'
let history = syncHistoryWithStore(hashHistory, store)
let rootElement = document.getElementById('contain');
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={Share}>
<Route path="user" component={User}/>
<Route path="field" component={Field}/>
<Route path="course" component={Course}/>
<Route path="section/:id" component={Section}/>
<Route path="lesson/:id" component={Lesson}/>
</Route>
</Router>
</Provider>,
rootElement
);

index.js的作用主要是把所有的东西连在一起,这里使用了react-router中的 syncHistoryWithStore 函数去做前端路由,这样我的单页面应用就建起来了.

  

linux下mysql的安装与简单操作

发表于 2016-06-01 | 分类于 后端

1.安装命令如下

sudo apt-get install mysql-server
然后按照提示输入数据库密码即可

2.启动mysql命令

service mysql start
这时系统会提示输入密码,正确输入后没有报错就是启动成功了

3.关闭mysql服务

service mysql stop

4.连接数据库

mysql -u root -p
这时系统会提示输入密码,正确输入后会进去mysql命令行下

5.查看数据库

show databases;
需要注意的是mysql命令后面一定要加分号,否则不会运行

6.创建数据库

create database name;

7.创建表

create table user(id int(3) auto_increment not null primary key, name char(8));

超文本编辑器simditor简单应用

发表于 2016-05-10 | 分类于 前端

我正在做一个在线考试的网站,那就需要老师布置试题,但是麻烦的是试题里面可能会有图片,答案里面也可能要有图片,所以就很麻烦,这时候想到了富文本编辑器,于是就发现了simditor,功能比较简单,加载也比较快
http://www.jq22.com/jquery-info590

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
<div class="am-g">
<div class="am-u-md-6 am-cf">
<div class="am-fl am-cf">
<div class="am-btn-toolbar am-fl">
<div class="am-btn-group am-btn-group-xs">
<button type="button" class="am-btn am-btn-default" id="b0"><span class="am-icon-plus"></span> 编辑题目</button>
</div>
<div class="am-btn-group am-btn-group-xs">
<button type="button" class="am-btn am-btn-default" id="b1"><span class="am-icon-plus"></span> A选项</button>
</div>
<div class="am-btn-group am-btn-group-xs">
<button type="button" class="am-btn am-btn-default" id="b2"><span class="am-icon-plus"></span> B选项</button>
</div>
<div class="am-btn-group am-btn-group-xs">
<button type="button" class="am-btn am-btn-default" id="b3"><span class="am-icon-plus"></span> C选项</button>
</div>
<div class="am-btn-group am-btn-group-xs">
<button type="button" class="am-btn am-btn-default" id="b4"><span class="am-icon-plus"></span> D选项</button>
</div>
</div>
</div>
</div>
<form class="am-form am-form-inline" style="display:inline-block;height:30px">
<div class="am-form-group " style="margin-bottom: 0">
<input type="number" id="score" placeholder="请输入分值" required>
</div>
<div class="am-form-group " style="margin-bottom: 0;width: 100px">
<select required id="answer">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
</select>
<span class="am-form-caret"></span>
</div>
</form>
</div>
<br/>
<div class="am-g">
<div class=" am-u-sm-centered">
<textarea rows="5" placeholder="请输入内容" id="editor" autofocus></textarea>
<br/>
<button type="button" id="submit" class="am-btn am-btn-primary am-radius" style="position: absolute;right: 5%;bottom: 0">提交</button>
</div>
</div>

html主要代码如上,下面介绍一下simditor的用法

1
2
3
4
5
6
7
8
9
10
11
12
<!--首先在网页中引用css和js文件-->
<link href="~/Scripts/bower_components/fontawesome/css/font-awesome.css" rel="stylesheet" />
<link href="~/Scripts/bower_components/simditor/styles/simditor.css" rel="stylesheet" />
<link href="~/Scripts/bower_components/simditor-emoji/styles/simditor-emoji.css" rel="stylesheet" />
<script src="/Scripts/bower_components/jquery/dist/jquery.min.js"></script>
<script src="~/Scripts/bower_components/simple-module/lib/module.js"></script>
<script src="~/Scripts/bower_components/simple-hotkeys/lib/hotkeys.js"></script>
<script src="~/Scripts/bower_components/simple-uploader/lib/uploader.js"></script>
<script src="~/Scripts/bower_components/simditor/lib/simditor.js"></script>
<script src="~/Scripts/bower_components/simditor-emoji/lib/simditor-emoji.js"></script>
<script src="~/Scripts/bower_components/simditor-markdown/lib/simditor-markdown.js"></script>

接着初始化编辑器

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
<script>
var editor = new Simditor({
textarea: $('#editor'),
toolbar: [
'title',
'bold',
'underline',
'strikethrough',
'color',
'ol', 'ul',
'blockquote',
'code',
'table',
'link',
'image',
'hr',
'indent', 'outdent',
'emoji'
],
upload: {
'url': '/Common/Upload/Index',
'connectionCount': 8
},
pasteImage: true,
emoji: {
imagePath: '/Scripts/bower_components/simditor-emoji/images/emoji/'
},
markdown: true
});
</script>

这样编辑器就可以使用了,下面是一些编辑试题的逻辑

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
<script>
$(function () {
var t = $("#editor");
var t0 = [];
var t1 = [];
var t2 = [];
var t3 = [];
var t4 = [];
var score = $("#score");
var trueop =$("#answer");
var nowT = t0;
$("#b0").click(function () {
nowT[0]= t.val();
nowT = t0;
editor.setValue(t0);
});
$("#b1").click(function () {
nowT[0] = t.val();
nowT = t1;
editor.setValue(t1);
});
$("#b2").click(function () {
nowT[0] = t.val();
nowT = t2;
editor.setValue(t2);
});
$("#b3").click(function () {
nowT[0] = t.val();
nowT = t3;
editor.setValue(t3);
});
$("#b4").click(function () {
nowT[0] = t.val();
nowT = t4;
editor.setValue(t4);
});
$("#submit").click(function () {
nowT[0] = t.val();
if (t0 == [""]) {
alert("题目不能为空");
}
else if (t1 == [""]) {
alert("A选项不能为空");
}
else if (t2 == [""]) {
alert("B选项不能为空");
}
else if (t3 == [""]) {
alert("C选项不能为空");
}
else if (t4 == [""]) {
alert("D选项不能为空");
}
else if (score.val()==0) {
alert("分值不能为空");
}
else if (trueop.val() == [""]) {
alert("答案不能为空");
} else {
$.ajax({
url: "/Admin/Questions/AddTest",
data: {
content: t0[0],
aop: t1[0],
bop: t2[0],
cop: t3[0],
dop: t4[0],
correctop: trueop.val(),
score: score.val()
},
success: function (res) {
if (res == 0) {
alert("添加失败");
} else {
alert("成功");
window.location.href = "/Admin/Questions/Add";
}
}
});
}
});
});
</script>

自此终于搞定了这个问题,这个过程用到了一些东西,ajax,simditor,还有文件上传,通过一步步的调试,改bug,越来越熟练网页的开发,没发现simditor之前本来还天真的想自己解决这个问题,既然有成熟的插件,就要学会去用,这样不只会节省时间,而且效果也非常好。

Simple-Calendar开发文档

发表于 2016-04-25 | 分类于 前端

##获取Simple-Calendar
从GitHub上下载 链接

##引入资源

使用日历插件前首先要引用资源:JS CSS

1
2
3
<link rel="stylesheet" type="text/css" href="css/simple-calendar.css">
<script type="text/jacascrip" src="js/simple-calendar.js"></script>

##初始化一个日历

首先为calendar准备一个容器,可以设置大小,也可以在options中设置,不设置的话自动设为默认

1
<div id='container'></div>

1
2
3
<script>
var myCalendar = new SimpleCalendar('#container');
</script>

这样一个日历就诞生了 ^-^

##配置项说明

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
var options = {
width: '500px',
height: '500px',
language: 'CH', //语言
showLunarCalendar: true, //阴历
showHoliday: true, //休假
showFestival: true, //节日
showLunarFestival: true, //农历节日
showSolarTerm: true, //节气
showMark: true, //标记
timeRange: {
startYear: 1900,
endYear: 2049
},
mark: {
'2016-5-5': '上学'
},
theme: {
changeAble: false,
weeks: {
backgroundColor: '#FBEC9C',
fontColor: '#4A4A4A',
fontSize: '20px',
},
days: {
backgroundColor: '#ffffff',
fontColor: '#565555',
fontSize: '24px'
},
todaycolor: 'orange',
activeSelectColor: 'orange',
}
}

国际化

language:
语言的话目前只支持中文和英文,分别对应’CH’,’EN’

如果想要加更多的语言或者更改现在的显示,可以直接更改languageData内容

节日显示配置

1
2
3
4
5
6
showLunarCalendar: true, //是否显示阴历日期
showHoliday: true, //是否显示休假休假
showFestival: true, //是否显示国际节日
showLunarFestival: true, //是否显示农历节日
showSolarTerm: true, //是否显示节气
showMark: true, //是否显示标记日期

时间范围

这个时间范围设置的是下拉框中的年数范围

1
2
3
4
timeRange: {
startYear: 1900,
endYear: 2049
}

标记日期

标记日期配置只有在 showMark 为 true 时才会生效

1
2
3
mark: {
'2016-5-5': '上学'
}

这样就会在日历的对应日期上面添加标记,当鼠标停留时显示输入的信息

主题配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
theme: {
changeAble: false,
weeks: {
backgroundColor: '#FBEC9C',
fontColor: '#4A4A4A',
fontSize: '20px',
},
days: {
backgroundColor: '#ffffff',
fontColor: '#565555',
fontSize: '24px'
},
todaycolor: 'orange',
activeSelectColor: 'orange',
}

主题配置只有在changeAble 为 true 时才会生效
weeks 设置的是星期一栏的主题,分别对应背景颜色,字体颜色,字体大小
days 设置的是日期的主题,参数同上
todaycolor 设置的是当天的日期背景颜色
activeSelectColor 设置的是鼠标滑过事件对应日期的边框颜色

事件接口说明

1
2
3
4
5
6
7
8
9
myCalendar.updateSize('500px', '500px');
myCalendar.addMark('2016-3-7', 'test');
myCalendar.setLanguage('EN')
myCalendar.showFestival(false);
myCalendar.showLunarCalendar(false);
myCalendar.showHoliday(false);
myCalendar.showSolarTerm(false);
myCalendar.showLunarFestival(false);
myCalendar.showMark(false);

updateSize(width,height)

调整日历大小,会自动根据大小调整对应的样式

addMark(day, info)

day 是一个可以确定一个日期的字符串
info 是要显示的信息

setLenguage(languageStr)

设置语言,目前支持的语言有’CH’,’EN’
如果想要增加语言,请在languageData中修改

其他

1
2
3
4
5
6
7
8
9
10
11
12
//关闭或者显示国际节日
showFestival(false);
//关闭或者显示阴历日期
showLunarCalendar(false);
//关闭或者显示假期
showHoliday(false);
//关闭或者显示二十四节气
showSolarTerm(false);
//关闭或者显示阴历节日
showLunarFestival(false);
//关闭或者显示标记
showMark(false)

Koajs+sequelize+mysql环境搭建

发表于 2016-04-25 | 分类于 后端

1.首先通过npm init 创建package.json文件

$ npm init

2.安装Koajs

$ npm install koa –save

在根目录下创建一个app.js的文件

1
2
3
4
5
6
7
8
var koa = require('koa');
var app = koa();
app.use(function *(){
this.body = 'Hello Lxc';
});
app.listen(3000);

3.启动服务器

$ node –harmony app.js

我们在浏览器中输入 http://localhost:3000就可以看见正确的输出了

4.在工程中安装mysql和sequelize

$ npm install mysql –save

$ npm install sequelize –save

5.数据库配置

在根目录下新建一个models文件夹,在里面新建一个config.js的数据库配置文件

1
2
3
4
5
6
7
8
9
10
11
12
module.exports = {
db: {
name: 'mysql',
username: 'root',
pwd: 'xxxxxx',
host: '127.0.0.1',
database: 'test',
toString() {
return `${this.name}://${this.username}:${this.pwd}@${this.host}/${this.database}`;
}
},
};

再新建一个db.js文件,引入config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Created by lxc on 16-3-3.
*/
var Sequelize = require('sequelize');
var configs = require('./config.js');
var sequelize = new Sequelize(configs.db.toString(), {
logging: function () {}
});
sequelize.define('message', {
title: Sequelize.TEXT,
link: Sequelize.TEXT});
sequelize.sync({
force: true
});

接下来我们在命令行中运行db.js

node db.js

完成后我们去sql查看是否创建成功

mysql> show columns from messages;
+———–+———-+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+———–+———-+——+—–+———+—————-+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | text | YES | | NULL | |
| link | text | YES | | NULL | |
| createdAt | datetime | NO | | NULL | |
| updatedAt | datetime | NO | | NULL | |
+———–+———-+——+—–+———+—————-+
5 rows in set (0.00 sec)

看到这个结果就是创建成功了^-^

这个应用的结构还比较简单,正常开发的话肯定要比这复杂的多,项目的结构都要考虑,如果以后有时间再来补充吧。

AnjularJS学习笔记

发表于 2016-04-10 | 分类于 前端

以前也接触过Angularjs,也用过一些,如今又回来重新看看,想理解的更深刻一些,写的可能不是很详细,但却是都是我学习的历程。

1. 安装

安装方式可以自己选择,可以去网上下载,下载地址:
http://angularjs.org;

也可以直接引用:

1
<script src="http://code.angularjs.org/angular-1.0.1.min.js"></script>

我是用的bower:

bower install angularjs -save

1
<script src='bower_components/angular/angular.js'></script>

2. HelloWold

1
2
3
<body ng-app>
hello {{'world!'}}
</body>

这样浏览器中就会打印出hello world!啦!

3. ng-app

ng-app指令标记了AngularJS脚本的作用域,在<html>中添加ng-app属性即说明整个<html>都是AngularJS脚本作用域。也可以在局部使用ng-app指令,像上面的例子<body ng-app>,则AngularJS脚本仅在该<body>中运行。
注:全局仅可以有一个ng-app

4. ng-controller

什么是controller,这就涉及到模型-视图-控制器(MVC)模式了
ng-controller命令就是绑定controller的命令,而他的作用域也只是在绑定的标签之下
看下面一段代码:

1
2
3
4
5
6
7
8
9
<body ng-app='myApp'>
hello {{'world!'}}
<div ng-controller='myCtrl'>
<div> {{myinfo.name}} </div>
</div>
<div ng-controller='youCtrl'>
<div> {{youinfo.name}} </div>
</div>
</body>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var app = angular.module('myApp', []);
app.controller('myCtrl', ['$scope',
function($scope) {
var people = new Object();
people.name='lxc';
people.age=22;
$scope.myinfo=people;
}
]);
app.controller('youCtrl', ['$scope',
function($scope) {
var people = new Object();
people.name = 'you';
people.age = 2;
$scope.youinfo = people;
}
]);

我在js中首先定义了一个myApp,在myApp下又定义了两个controller,myCtrl和youCtrl,在控制器中分别初始化两个people;
在html中我分别将两个控制器绑定div,在其中打印出name
这时看看正确结果:

hello world!
lxc
you

下面我们来试验一下一个controller中的值可不可以在绑定的表情外部访问或者在其他controller中访问:
js不动,更改html代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
<body ng-app='myApp'>
hello {{'world!'}}
<div ng-controller='myCtrl'>
<div> {{myinfo.name}} </div>
<div>test: {{youinfo.name}} </div>
</div>
<div ng-controller='youCtrl'>
<div> {{youinfo.name}} </div>
<div>test: {{myinfo.name}} </div>
</div>
<div>test: {{youinfo.name}} </div>
<div>test: {{youinfo.name}} </div>
</body>

结果如下:

hello world!
lxc
test:
you
test:
test:
test:

我们发现一个controller中的元素只能在自己的作用域中访问,那我们要想访问另一个controller中的元素怎么办呢?
答案是:

  • 利用作用域继承的原理,子控制器访问父级控制器中的内容。
  • 使用angularJS中的事件,也就是使用$on,$emit,$broadcast进行消息传递
  • 使用angularJS中的服务

5. 一些指令

(1)ng-repeat

这是一个循环指令
下面看个例子:

1
2
3
4
5
var list=['lxc1','lxc2','lxc3'];
$scope.list=list;
$scope.changelist=function(){
list.push('lxc4');
}

1
2
3
4
5
<li ng-repeat='i in list'>
{{i}}
</li>
<button ng-click='changelist()'>changelist()</button>

界面显示如下

lxc1
lxc2
lxc3

这时我们点击changelist()看看发生了什么:

lxc1
lxc2
lxc3
lxc4

我们发现数组的更改直接反应在了html上,这就是angular的优点,以前的话还要用jQuery再在html中加一个标签,现在这些事情angular都为我们做了,是不是很方便^-^

(2) ng-click

这个已经在上面的例子总用到了,可以为标签的点击事件绑定对应作用域中的一个方法,也是很方便

(3) ng-model

ng-model 指令可以将输入域的值与 AngularJS 创建的变量绑定。

1
2
3
4
<input ng-model='name' />
<input value="{{name}}" />
<input ng-model='name' />
<div ng-bind="name"> </div>

运行之后我们发现在第一个input中输入值可以下面三个标签上显示,改变第三个其他三个也会跟着改变,但是改变第二个就只会他自己改变,这也很好解释,因为第二个input只是用来显示name的值,并没有进行双向绑定

下面我们看看在html中通过ng-model定义的name在js中可不可以访问

1
2
3
4
5
<input ng-model='name' />
<input value="{{name}}" />
<input ng-model='name' />
<div ng-bind="name"> </div>
<button ng-click='showevent()'>alert()</button>

1
2
3
$scope.showevent=function(){
alert($scope.name);
}

在input中输入一个值,点击按钮,发现浏览器正确的输出了name的值

(4) ng-options

1
2
3
<select ng-model='select' ng-change='selectchange()' ng-options='i.url as i.site for i in sites'>
<option value="">请选择</option>
</select>
1
2
3
4
5
6
7
8
$scope.sites = [
{site : "Google", url : "http://www.google.com"},
{site : "Baidu", url : "http://www.baidu.com"},
{site : "Taobao", url : "http://www.taobao.com"}
];
$scope.selectchange=function(){
alert($scope.select);
}

刷新界面发现select已经正确的显示出来了,我们去改变他,发现浏览器也能正确的输出改变后的值

在上面使用了ng-change,其实和正常的onchange事件类似,都是在值发生改变时触发

(5)ng-disabled

1
<button ng-disabled='1' ng-click='changeselect()' >changeselect</button>

这个很简单,当他的值为不等于0和false时,angular就会给button加上disabled="disabled"属性

当然其他指令还有很多,下次在介绍吧^-^

Javascript 数组操作

发表于 2016-03-28

1.新建数组

1
2
3
4
5
6
7
//可以省略new
var colors = new Array();
var colors = new Array(20);
var colors = new Array("red", "blue", "green");
var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
var names = []; // 创建一个空数组

2.检测数组

1
2
3
4
5
6
7
8
if (value instanceof Array){
//对数组执行某些操作
}
//推荐下面这种方式
if (Array.isArray(value)){
//对数组执行某些操作
}

3.栈方法和队列方法

push() 方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度
pop() 方法则从数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项
shift() 它能够移除数组中的第一个项并返回该项,同时将数组长度减 1
unshift()它能在数组前端添加任意个项并返回新数组的长度
例:

1
2
3
4
5
6
7
8
var colors = new Array(); // 创建一个数组
var count = colors.push("red", "green"); // 推入两项
alert(count); //2
count = colors.push("black"); // 推入另一项
alert(count); //3
var item = colors.pop(); // 取得最后一项
alert(item); //"black"
alert(colors.length); //2

4.转换方法

1
2
3
4
var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
alert(colors.toString()); // red,blue,green
alert(colors.valueOf()); // red,blue,green
alert(colors); // red,blue,green

alert() 会自动调用toString()方法

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var person1 = {
toLocaleString : function () {
return "Nikolaos";
},
toString : function() {
return "Nicholas";
}
};
var person2 = {
toLocaleString : function () {
return "Grigorios";
},
toString : function() {
return "Greg";
}
};
var people = [person1, person2];
alert(people); //Nicholas,Greg
alert(people.toString()); //Nicholas,Greg
alert(people.toLocaleString()); //Nikolaos,Grigorios

join()方法 可以使用不同的分隔符来构建这个字符串

1
2
3
var colors = ["red", "green", "blue"];
alert(colors.join(",")); //red,green,blue
alert(colors.join("||")); //red||green||blue

5.排序方法

reverse() 方法会反转数组项的顺序

1
2
3
ar values = [1, 2, 3, 4, 5];
values.reverse();
alert(values); //5,4,3,2,1

sort() 方法按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。
为了实现排序, sort() 方法会调用每个数组项的 toString() 转型方法,然后比较得到的字符串,以确定如何排序。
即使数组中的每一项都是数值, sort() 方法比较的也是字符串

1
2
3
var values = [0, 1, 5, 10, 15];
values.sort();
alert(values); //0,1,10,15,5

sort()自定义排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
var values = [0, 1, 5, 10, 15];
values.sort(compare);
alert(values); //0,1,5,10,15
//数值型比较函数
function compare(value1, value2){
return value2 - value1;
}

6.操作方法

concat() 方法可以基于当前数组中的所有项创建一个新数组

1
2
3
4
var colors = ["red", "green", "blue"];
var colors2 = colors.concat("yellow", ["black", "brown"]);
alert(colors); //red,green,blue
alert(colors2); //red,green,blue,yellow,black,brown

slice() 它能够基于当前数组中的一或多个项创建一个新数组。
slice() 方法可以接受一或两个参数,即要返回项的起始和结束位置
在只有一个参数的情况下, slice() 方法返回从该
参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项—但不包括结束位置的项

1
2
3
4
5
var colors = ["red", "green", "blue", "yellow", "purple"];
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,4);
alert(colors2); //green,blue,yellow,purple
alert(colors3); //green,blue,yellow

splice() 方法,这个方法恐怕要算是最强大的数组方法了,它有很多种用。
splice() 的主要用途是向数组的中部插入项,但使用这种方法的方式则有如下 3 种

删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。
例如, splice(0,2) 会删除数组中的前两项。
插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、0(要删除的项数)
和要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。例如,
splice(2,0,”red”,”green”) 会从当前数组的位置 2 开始插入字符串 “red” 和 “green” 。
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,
splice (2,1,”red”,”green”) 会删除当前数组位置 2 的项,然后再从位置 2 开始插入字符串”red” 和 “green” 。
splice() 方法始终都会返回一个数组,该数组中包含从原始数组中删除的项(如果没有删除任何项,则返回一个空数组) 。下面的代码展示了上述 3 种使用 splice() 方法的方式

1
2
3
4
5
6
7
8
9
10
var colors = ["red", "green", "blue"];
var removed = colors.splice(0,1); // 删除第一项
alert(colors); // green,blue
alert(removed); // red,返回的数组中只包含一项
removed = colors.splice(1, 0, "yellow", "orange"); // 从位置 1 开始插入两项
alert(colors); // green,yellow,orange,blue
alert(removed); // 返回的是一个空数组
removed = colors.splice(1, 1, "red", "purple"); // 插入两项,删除一项
alert(colors); // green,red,purple,orange,blue
alert(removed); // yellow,返回的数组中只包含一项

7.位置方法

indexOf() 和 lastIndexOf() 。这两个方法都接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中,indexOf() 方法从数组的开头(位置0)开始向后查找,lastIndexOf() 方法则从数组的末尾开始向前查找

1
2
3
4
5
6
7
8
9
10
var numbers = [1,2,3,4,5,4,3,2,1];
alert(numbers.indexOf(4)); //3
alert(numbers.lastIndexOf(4)); //5
alert(numbers.indexOf(4, 4)); //5
alert(numbers.lastIndexOf(4, 4)); //3
var person = { name: "Nicholas" };
var people = [{ name: "Nicholas" }];
var morePeople = [person];
alert(people.indexOf(person)); //-1
alert(morePeople.indexOf(person)); //0

8.迭代方法

every() :对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true 。

filter() :对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。

forEach() :对数组中的每一项运行给定函数。这个方法没有返回值。

map() :对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组

some() :对数组中的每一项运行给定函数,如果该函数对任一项返回 true ,则返回 true 。

every() 和 some() ,它们都用于查询数组中的项是否满足某个条件

1
2
3
4
5
6
7
8
9
var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item, index, array){
return (item > 2);
});
alert(everyResult); //false
var someResult = numbers.some(function(item, index, array){
return (item > 2);
});
alert(someResult); //true

filter() 它利用指定的函数确定是否在返回的数组中包含某一项

1
2
3
4
5
var numbers = [1,2,3,4,5,4,3,2,1];
var filterResult = numbers.filter(function(item, index, array){
return (item > 2);
});
alert(filterResult); //[3,4,5,4,3]

map() 也返回一个数组,而这个数组的每一项都是在原始数组中的对应项上运行传入函数的结果

1
2
3
4
5
var numbers = [1,2,3,4,5,4,3,2,1];
var mapResult = numbers.map(function(item, index, array){
return item * 2;
});
alert(mapResult); //[2,4,6,8,10,8,6,4,2]

forEach() ,它只是对数组中的每一项运行传入的函数。这个方法没有返回值,
本质上与使用 for 循环迭代数组一样

1
2
3
4
var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
//执行某些操作
});

9.归并方法

1
2
3
4
5
6
7
8
9
10
11
12
//使用 reduce() 方法可以执行求数组中所有值之和的操作,比如:
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15
//reduceRight() 的作用类似,只不过方向相反而已。来看下面这个例子。
var values = [1,2,3,4,5];
var sum = values.reduceRight(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15

js 原型方法 类方法 对象方法

发表于 2016-03-17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var people=function (name) {
this.name=name;
//对象方法
this.say=function () {
console.log(this.name);
}
}
//类方法
people.ssay=function () {
console.log('this:'+this);
}
var p1=new people('p1');
var p2=new people('p2');
//原型方法
people.prototype.psay=function () {
console.log('this:'+this.name);
}
p1.say();
p2.say();
p1.psay();
p2.psay();
people.ssay();

结果:

1
2
3
4
5
6
7
8
9
10
11
p1
p2
this:p1
this:p2
this:function (name) {
this.name=name;
//对象方法
this.say=function () {
console.log(this.name);
}
}

1. 对象方法

对象方法就是每个对象都会包括的一个方法,每个类的实例都可以调用

2. 类方法

每个类都相当于一个Object,类方法指的是这个Object里面的方法,只能通过类的名字调用,this指向这个类,不能通过实例调用

3. 原型方法

原型方法主要是用来对对已有的对象进行扩展的,看上面的代码,在对象已经实例化的时候添加原型方法,这时候每个实例都可以调用

OpenXml 操作Word Excel

发表于 2016-03-02 | 分类于 后端

下面是两篇参考博客
Word :http://blog.csdn.net/francislaw/article/details/7568317
Excel :http://www.cnblogs.com/BeyondWJsel/archive/2012/05/10/2494418.html

由于项目需要,我只学习了word插入文字部分,剩下的需要再回来看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//在word对应的mark位置插入文字
public void bookmark(WordprocessingDocument file, string markname, string str)
{
Dictionary<String, BookmarkStart> bookmarkMap =
new Dictionary<String, BookmarkStart>();
foreach (BookmarkStart bookmarkStart in file.MainDocumentPart.RootElement.Descendants<BookmarkStart>())
{
if (bookmarkStart.Name == markname)
{
var run = new Run();
run.Append(new Text(str));
bookmarkStart.InsertAfterSelf(run);
}
}
//foreach (BookmarkStart bookmarkStart in bookmarkMap.Values)
//{
// var run = new Run();
// run.Append(new Text("Hello World"));
// bookmarkStart.InsertAfterSelf(run);
//}
}
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
//打开一个word插入文字
public static void AddString(string filePath, string str)
{
using (WordprocessingDocument doc = WordprocessingDocument.Open(filePath, true))
{
Paragraph paragraph = new Paragraph();
Run run = new Run();
RunProperties runProperties = new RunProperties(); //属性
//RunFonts fonts = new RunFonts() { EastAsia = "DFKai-SB" }; // 设置字体
//FontSize size = new FontSize() { Val = "52" }; // 设置字体大小
//Color color = new Color() { Val = "red" }; // 设置字体样式
// 将样式添加到属性里面
//runProperties.Append(color);
//runProperties.Append(size);
//runProperties.Append(fonts);
//run.Append(runProperties);
run.Append(new Text(str));
paragraph.Append(run);
doc.MainDocumentPart.Document.Body.Append(paragraph);
doc.MainDocumentPart.Document.Save();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//根据文字新建word
public void Create(string filePath, string str)
{
var psth = Server.MapPath(@"~/Word");
using (WordprocessingDocument doc = WordprocessingDocument.Create(psth + "\\t.docx", WordprocessingDocumentType.Document))
{
// ②:为doc添加MainDocumentPart部分
MainDocumentPart mainPart = doc.AddMainDocumentPart();
// ③:为mainPart添加Document,对应于Word里的文档内容部分
mainPart.Document = new Document();
// ④:为Document添加Body,之后所有于内容相关的均在此body中
Body body = mainPart.Document.AppendChild(new Body());
// ⑤:添加段落P,P中包含一个文本“TEST”
Paragraph p = mainPart.Document.Body.AppendChild(new Paragraph());
p.AppendChild(new Run(new Text("TEST")));
}
}
123
李续铖

李续铖

21 日志
4 分类
11 标签
GitHub 微博 知乎
© 2017 李续铖