iscroll bouncefix fastclick的渊源....

iscroll v5

原本的目的是想看懂iscroll源码就为了知道他是怎么实现bounce的,结果发现他解决了很多问题

1 fixed定位
2 < iOS8 scroll事件触发问题
3 进而又了解到sticky细节问题以及。。。

Fluxxor

fluxxor

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
var React = require("react"),
Fluxxor = require("../../../");
window.React = React;
var constants = {
ADD_TODO: "ADD_TODO",
TOGGLE_TODO: "TOGGLE_TODO",
CLEAR_TODOS: "CLEAR_TODOS"
};
var TodoStore = Fluxxor.createStore({
initialize: function() {
this.todoId = 0;
this.todos = {};
this.bindActions(
constants.ADD_TODO, this.onAddTodo,
constants.TOGGLE_TODO, this.onToggleTodo,
constants.CLEAR_TODOS, this.onClearTodos
);
},
onAddTodo: function(payload) {
debugger;

var id = this._nextTodoId();
var todo = {
id: id,
text: payload.text,
complete: false
};
console.log('TodoStore');
this.todos[id] = todo;
this.emit("change");
},
onToggleTodo: function(payload) {

var id = payload.id;
this.todos[id].complete = !this.todos[id].complete;
this.emit("change");

},
onClearTodos: function() {
var todos = this.todos;
Object.keys(todos).forEach(function(key) {
if(todos[key].complete) {
delete todos[key];
}
});
this.emit("change");
},
getState: function() {
return {
todos: this.todos
};
},
_nextTodoId: function() {
return ++this.todoId;
}
});
var actions = {
addTodo: function(text) {
console.log('action');
this.dispatch(constants.ADD_TODO, {text: text});
},
toggleTodo: function(id) {
this.dispatch(constants.TOGGLE_TODO, {id: id});
},
clearTodos: function() {
this.dispatch(constants.CLEAR_TODOS);
}
};
var stores = {
TodoStore: new TodoStore()
};
var flux = new Fluxxor.Flux(stores, actions);
window.flux = flux;
flux.on("dispatch", function(type, payload) {
debugger;

if (console && console.log) {
console.log("[Dispatch]", type, payload);
}
});
var FluxMixin = Fluxxor.FluxMixin(React),
StoreWatchMixin = Fluxxor.StoreWatchMixin;
var Application = React.createClass({
mixins: [FluxMixin, StoreWatchMixin("TodoStore")],
getInitialState: function() {
return { newTodoText: "" };
},
getStateFromFlux: function() {
var flux = this.getFlux();
// Our entire state is made up of the TodoStore data. In a larger
// application, you will likely return data from multiple stores, e.g.:
// return {
// todoData: flux.store("TodoStore").getState(),
// userData: flux.store("UserStore").getData(),
// fooBarData: flux.store("FooBarStore").someMoreData()
// };
return flux.store("TodoStore").getState();
},
render: function() {
var todos = this.state.todos;
return (
<div>
<ul>
{Object.keys(todos).map(function(id) {
return <li key={id}><TodoItem todo={todos[id]} /></li>;
})}
</ul>
<form onSubmit={this.onSubmitForm}>
<input type="text" size="30" placeholder="New Todo"
value={this.state.newTodoText}
onChange={this.handleTodoTextChange} />
<input type="submit" value="Add Todo" />
</form>
<button onClick={this.clearCompletedTodos}>Clear Completed</button>
</div>
);
},
handleTodoTextChange: function(e) {
this.setState({newTodoText: e.target.value});
},
onSubmitForm: function(e) {
e.preventDefault();
if (this.state.newTodoText.trim()) {
this.getFlux().actions.addTodo(this.state.newTodoText);
this.setState({newTodoText: ""});
}
},
clearCompletedTodos: function(e) {
this.getFlux().actions.clearTodos();
}
});
var TodoItem = React.createClass({
mixins: [FluxMixin],
propTypes: {
todo: React.PropTypes.object.isRequired
},
render: function() {
var style = {
textDecoration: this.props.todo.complete ? "line-through" : ""
};
return <span style={style} onClick={this.onClick}>{this.props.todo.text}</span>;
},
onClick: function() {
this.getFlux().actions.toggleTodo(this.props.todo.id);
}
});
React.render(<Application flux={flux} />, document.getElementById("app"));

React Tutorial(0.14)

Client

本地server跑起来 3000端口

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./build/react.min.js"></script>
<script src="./build/react-dom.min.js"></script>
<script src="./babel.js"></script>
<script src="./jquery.2.1.1.min.js"></script>
<script src="./marked.min.js"></script>
<style>
</style>

</head>
<body>
<div id="content"></div>
<script type="text/babel">
//1
var Comment = React.createClass({
rawMarkup: function() {
var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
return { __html: rawMarkup };
},
render: function() {
return (
<div className="comment">
<h2 className="commentAuthor">
{this.props.author}
</h2>
<span dangerouslySetInnerHTML={this.rawMarkup()} />
</div>
);
}
});
//2
var CommentBox = React.createClass({
loadCommentsFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
handleCommentSubmit: function(comment) {
var comments = this.state.data;
console.log('sasdasdasd');
// Optimistically set an id on the new comment. It will be replaced by an
// id generated by the server. In a production application you would likely
// not use Date.now() for this and would have a more robust system in place.
comment.id = Date.now();
var newComments = comments.concat([comment]);
this.setState({data: newComments});
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: comment,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
});
//3
var CommentList = React.createClass({
render: function() {
var commentNodes = this.props.data.map(function(comment) {
return (
<Comment author={comment.author} key={comment.id}>
{comment.text}
</Comment>
);
});
return (
<div className="commentList">
{commentNodes}
</div>
);
}
});
//4
var CommentForm = React.createClass({
getInitialState: function() {
return {author: '', text: ''};
},
handleAuthorChange: function(e) {
this.setState({author: e.target.value});
},
handleTextChange: function(e) {
this.setState({text: e.target.value});
},
handleSubmit: function(e) {
console.log('liuyangzuo')
e.preventDefault();
var author = this.state.author.trim();
var text = this.state.text.trim();
if (!text || !author) {
return;
}
// TODO: send request to the server
this.props.onCommentSubmit({author: author, text: text});
this.setState({author: '', text: ''});
},
render: function() {
return (
<form className="commentForm" onSubmit={this.handleSubmit}>
<input
type="text"
placeholder="Your name"
value={this.state.author}
onChange={this.handleAuthorChange}
/>
<input
type="text"
placeholder="Say something..."
value={this.state.text}
onChange={this.handleTextChange}
/>
<input type="submit" value="Post" />
</form>
);
}
});
ReactDOM.render(
<CommentBox url="http://localhost:8080" pollInterval={2000} />,
document.getElementById('content')
);
</script>

</body>
</html>

Server

监听8080端口

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
var express = require("express");
var bodyParser = require("body-parser");
var cors = require("cors");
var app = express();
// app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors());


var obj = [
{id: 1, author: "于洪洋", text: "是我"},
{id: 2, author: "于四蛋", text: "就是我"},
{id: 3, author: "于四驴", text: "一定是我"}
];
var i = 10;
/*
setInterval(function(){
i++
obj.push({ id:i,author:"于"+i,text:"是我" +i });
},1000)
*/

var postData = [];
app.get('/',function(req,res){
res.json(obj);
})
app.post('/',function(req,res){
console.log(req.body)
})
app.listen(8080);

cookie-parser

1
cookieParser.signedCookie('s:foobar.N5r0C3M8W+IPpzyAJaIddMWbTGfDSO+bfKlZErJ+MeE', 'keyboard cat');

express学习

connect中间件

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
var connect = require("connect");
var app = connect();



function logger(req,res,next){
console.log('logger');
next()
}
function hello(req,res){
console.log('hello');
res.end("Hello World!");
}

function authenticateWithDatabase(user, pass, callback) {
var err;
if (user != 'tobi' || pass != 'ferret') {
err = new Error('Unauthorized');
}
callback(err);
}

function restrict(req,res,next){
var authorization = req.headers.authorization;
if( !authorization ){
return next(new Error('Unathorized'));
}
var parts = authorization.split(' ');
var scheme = parts[0];
var auth = new Buffer(parts[1],'base64').toString().split(":");
var user = auth[0];
var pass = auth[1];

authenticateWithDatabase(user,pass,function(err){
if(err){
return next(err);
}
next()
});
}
function admin(req,res,next){
switch (req.url) {
case '/':
res.end('try /users');
break;
case '/users':
res.setHeader('Content-tyep','application/json');
res.end(JSON.stringify(['tobi','loki','jane']))
break;
}
}

app.use(logger)
.use('/admin',restrict)
.use('/admin',admin)
.use(hello)
app.listen(8080);

swipe 源码解析

WebSocket

Node CORS