我尝试使用Cyclejs/xstream
. 该应用程序运行良好。唯一我无法理解的是在添加每个待办事项后输入应该清除,这没有发生。
todo.js
import {
div, span, p, input, ul, li, button, body
}
from '@cycle/dom'
import xs from 'xstream'
import Utils from './utils'
export function Todo(sources) {
const sinks = {
DOM: view(model(intent(sources)))
}
return sinks
}
function intent(sources) {
return {
addTodo$: sources.DOM.select('input[type=text]').events('keydown').filter((ev) => {
return ev.which == 13 && ev.target.value.trim().length > 0;
}).map((ev) => {
return ev.target.value;
}),
deleteTodo$: sources.DOM.select('.delete').events('click').map((ev) => {
return Number(ev.target.getAttribute('data-id'));
}).filter((id) => {
return !isNaN(id);
}),
completeTodo$: sources.DOM.select('.complete').events('click').map((ev) => {
return Number(ev.target.getAttribute('data-id'));
}).filter((id) => {
return !isNaN(id);
})
};
}
function model(action$) {
let deleteTodo$ = action$.deleteTodo$.map((id) => {
return (holder) => {
let index = Utils.findIndex(holder.currentTodos, 'id', id);
if (index > -1) holder.currentTodos.splice(index, 1);
return {
currentTodos: holder.currentTodos,
value: ''
};
};
});
let completeTodo$ = action$.completeTodo$.map((id) => {
return (holder) => {
let index = Utils.findIndex(holder.currentTodos, 'id', id);
if (index > -1) holder.currentTodos[index].completed = !holder.currentTodos[index].completed;
return {
currentTodos: holder.currentTodos,
value: ''
};
};
});
let addTodo$ = action$.addTodo$.map((item) => {
return (holder) => {
let todo = {
value: item,
id: holder.currentTodos.length + 1,
completed: false
};
holder.currentTodos.push(todo);
return {
currentTodos: holder.currentTodos,
value: ''
};
};
});
return xs.merge(deleteTodo$, addTodo$, completeTodo$)
.fold((holder, modifier) => {
return modifier(holder);
}, {
currentTodos: [],
value: ''
});
}
function view(state$) {
return state$.map((state) => {
console.log(state);
return div({
attrs: {
class: 'todo'
}
}, [
input({
props: {
type: 'text',
value: state.value
}
}),
ul({
attrs: {
class: 'text'
}
}, state.currentTodos.map((todo) => {
return li({
attrs: {
class: `${todo.completed ? 'completed' : 'open'}`
}
}, [
span(todo.value),
button({
attrs: {
class: 'delete',
'data-id': todo.id
}
}, 'XXXXX'),
button({
attrs: {
class: 'complete',
'data-id': todo.id
}
}, 'CCCCC')
]);
}))
]);
});
}
实用程序.js
var Utils = {
filter: function(array, fn) {
var results = [];
var item;
for (var i = 0, len = array.length; i < len; i++) {
item = array[i];
if (fn(item)) results.push(item);
}
return results;
},
findItem: function(array, fn) {
for (var i = 0, len = array.length; i < len; i++) {
var item = array[i];
if (fn(item)) return item;
}
return null;
},
findIndex: function(array, prop, value) {
var pointerId = -1;
var index = -1;
var top = array.length;
var bottom = 0;
for (var i = array.length - 1; i >= 0; i--) {
index = bottom + (top - bottom >> 1);
pointerId = array[index][prop];
if (pointerId === value) {
return index;
} else if (pointerId < value) {
bottom = index;
} else if (pointerId > value) {
top = index;
}
}
return -1;
}
};
export default Utils;