重绘后 Cyclejs 输入未重置

Cyclejs input not resetting after redraw

我尝试使用 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')
                ]);
            }))
        ]);
    });
}

utils.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;

您需要将钩子放在输入元素中。它将按预期工作。如果你愿意,你可以发送另一个默认值(在这种情况下它是空字符串)。

input({
     props: {
          type: 'text'
     },
     hook: {
          update: (o, n) => n.elm.value = ''
     }
 }),

@cycle/dom 驱动程序应该 > 11.0.0 与 Snabbdom 一起工作。但是如果你使用早期版本你需要:

var Hook = function(){
    this.arguments=arguments;
}
Hook.prototype.hook = function(node) {
    node.value=this.arguments[0];
}


input({ attributes: {type: 'text'},
      'my-hook':new Hook('')
})