-
Notifications
You must be signed in to change notification settings - Fork 318
todolist与react redux
司徒正美 edited this page May 4, 2017
·
1 revision
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script type='text/javascript' src="./dist/React.js"></script>
<style>
.aaa {
width: 200px;
height: 200px;
background: red;
}
</style>
<!-- <script src="./test/react.js"></script>
<script src="./test/react-dom.js"></script>-->
<script src="./test/redux.js"></script>
<script src="./test/react-redux.js"></script>
<script src="./test/babel.js"></script>
<script type='text/babel'>
var combineReducers = Redux.combineReducers
var Provider = ReactRedux.Provider
var connect = ReactRedux.connect
const todo = (state, action) => {
switch (action.type) {
case 'ADD_TODO':
return {
id: action.id,
text: action.text,
completed: false
}
case 'TOGGLE_TODO':
if (state.id !== action.id) {
return state
}
return {
...state,
completed: !state.completed
}
default:
return state
}
}
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
todo(undefined, action)
]
case 'TOGGLE_TODO':
return state.map(t =>
todo(t, action)
)
default:
return state
}
}
const visibilityFilter = (state = 'SHOW_ALL', action) => {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter
default:
return state
}
}
const todoApp = combineReducers({
todos,
visibilityFilter
})
//===================filters
let nextTodoId = 0
const addTodo = (text) => ({
type: 'ADD_TODO',
id: nextTodoId++,
text
})
const setVisibilityFilter = (filter) => ({
type: 'SET_VISIBILITY_FILTER',
filter
})
const toggleTodo = (id) => ({
type: 'TOGGLE_TODO',
id
})
const Link = ({ active, children, onClick }) => {
if (active) {
return <span>{children}</span>
}
return (
<a href="#"
onClick={e => {
e.preventDefault()
onClick()
}}
>
{children}
</a>
)
}
const Todo = ({ onClick, completed, text }) => (
<li
onClick={onClick}
style={{
textDecoration: completed ? 'line-through' : 'none'
}}
>
{text}
</li>
)
const TodoList = function({ todos, onTodoClick }) {
return <ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
}
const Footer = () => (
<p>
Show:
{" "}
<FilterLink filter="SHOW_ALL">
All
</FilterLink>
{", "}
<FilterLink filter="SHOW_ACTIVE">
Active
</FilterLink>
{", "}
<FilterLink filter="SHOW_COMPLETED">
Completed
</FilterLink>
</p>
)
const App = () => (
<div>
<AddTodo />
<VisibleTodoList />
<Footer />
</div>
)
let AddTodo = ({ dispatch }) => {
let input
return (
<div>
<form onSubmit={e => {
e.preventDefault()
if (!input.value.trim()) {
return
}
dispatch(addTodo(input.value))
input.value = ''
}}>
<input ref={node => {
input = node
}} />
<button type="submit">
Add Todo
</button>
</form>(点列表前的圆点切换状态)
</div>
)
}
AddTodo = connect()(AddTodo)
const mapStateToProps = (state, ownProps) => ({
active: ownProps.filter === state.visibilityFilter
})
const mapDispatchToProps = (dispatch, ownProps) => ({
onClick: () => {
dispatch(setVisibilityFilter(ownProps.filter))
}
})
const FilterLink = connect(
mapStateToProps,
mapDispatchToProps
)(Link)
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_ALL':
return todos
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed)
default:
throw new Error('Unknown filter: ' + filter)
}
}
const mapStateToProps1 = (state) => ({
todos: getVisibleTodos(state.todos, state.visibilityFilter)
})
const mapDispatchToProps1 = {
onTodoClick: toggleTodo
}
const VisibleTodoList = connect(
mapStateToProps1,
mapDispatchToProps1
)(TodoList)
const store = Redux.createStore(todoApp)
var s
window.onload = function(){
s = ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('example')
)
}
</script>
</head>
<body>
<div>测试</div>
<blockquote id='example'></blockquote>
</body>
</html>
``html
<script type='text/javascript' src="./dist/React.js"></script> <script type='text/javascript' src="./test/react.development.js"></script> <script type='text/javascript' src="./test/react-dom.development.js"></script><script type='text/javascript' src="./lib/babel.js"></script>
<pre>应该等于
</pre>
<h1 id='root' class="root">
</h1>
<script type='text/babel'>
var container = document.getElementById("example")
var div = container
var PropTypes = React.PropTypes
if(!window.ReactDOM){
window.ReactDOM = React
}
var expect = function(a) {
return {
toBe: function(b) {
console.log(a,"vs", b, a === b)
},
toEqual(b){
console.log(a,"vs", b, a +""=== b+"")
},
toThrow(b){
try{
a()
}catch(e){
console.log(e,"vs", b, e.message +""=== b+"")
}
}
}
}
const Hello = ({ name }) => <h1>Hello {name}!</h1>;
class ShowMyError extends React.Component {
constructor(props) {
super(props);
this.state = { error: false };
}
componentDidCatch(error, info) {
console.log(error, info)
this.setState({ error, info });
}
render() {
if (this.state.error) {
return (
<div>
<h1>
Error AGAIN: {this.state.error.toString()}
</h1>
{this.state.info &&
this.state.info.componentStack.split("\n").map(i => {
return (
<div key={i}>
{i}
</div>
);
})}
</div>
);
}
return this.props.children;
}
}
class Broken extends React.Component {
constructor(props) {
super(props);
this.state = { throw: false, count: 0 };
}
render() {
if (this.state.throw) {
throw new Error("YOLO");
}
return (
<div>
<button
onClick={e => {
this.setState({ throw: true });
}}
>
button will render error.
</button>
<button onClick={e => {
this.setState(({ count }) => ({
count: count + 1
}));
}}>button will not throw</button>
<div>
{"All good here. Count: "}{this.state.count}
</div>
</div>
);
}
}
class App extends React.Component {
render() {
const styles = {
fontFamily: "sans-serif",
textAlign: "center"
};
return (
<div style={styles}>
<Hello name="ShowMyError" />
<h2>
Start clicking to see some {"\u2728"}magic{"\u2728"}
</h2>
<ShowMyError>
<Broken />
</ShowMyError>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));