javascript - 操作 DOM 时的数据绑定(bind)不适用于 Angular、Knockout

标签 javascript jquery angularjs knockout.js

我正在寻求实现 Angular、Knockout 或其他方法来数据绑定(bind)向导式应用程序以进行概念验证(无服务器端代码)。但是,当我克隆数据绑定(bind) div 时,我似乎破坏了数据绑定(bind)。

应用程序表单的前几个步骤捕获数据,而后面的步骤将数据返回给用户以允许他们确认输入的内容。我通过在按下“下一步”时插入适当的步骤并在按下“上一个”时取出最后一步来操作 DOM。我使用分离克隆删除来完成此操作。

任何人都可以就他们将采取的方法来完成这项工作以及我应该考虑哪些框架提供建议吗?

下面是给出结构概念的伪代码。伪数据绑定(bind)代码正是我所认为的工作方式,我没有依赖任何框架。

HTML View

<div id="wizard">
    <div id="step1">Enter your name: <input type="text" id="name" /></div>
</div>
<div id="actions"><input type="button" value="Previous" /><input type="button" value="Next" onClick="goNext();" /></div>

<div id="steps">
    <div id="stepA">Enter your age: <input type="text" id="age" databind="theAge" /></div>
    <div id="stepB">The age you entered - {{ theAge }} is too young!</div>
    <div id="stepC">Enter your favourite colour: <input type="text" id="faveColour" databind="faveCol" /></div>
    <div id="stepD">Hi {{ name }}. You are {{ age }} years old and your favourite colour is {{ faveCol }}</div>
</div>

JavaScript

<script>
function goNext() {
    // figure out which step is next
    insertStepIntoWizard(step, index, title);
}

function insertStepIntoWizard(step, index, title) {
    var element = step.detach();
    wizard.steps('insert', index, {
        title: title,
        content: element.clone()
    });
    console.log('insertStepIntoWizard - just inserted ' + step.attr('id') + ' into wizard position ' + index);
}
</script>

最佳答案

我认为您正在考虑让您的 View 反射(reflect)您的实体模型,这基本上是模板化。如果您希望使用 Knockout/Angular,除了控制实体之外,还可以考虑使用它的 View 模型来管理页面状态/流程/操作。 (编写 jQuery 代码来探索 DOM 和克隆、显示/隐藏等并不有趣)。 @sabithpocker 也提出了类似的观点。

工作示例:我熟悉 Knockout,并为您的场景创建了一个示例 jsFiddle:http://jsfiddle.net/overflew/BfRq8/5/

注释:

  • 我使用 template 标签来容纳向导的每个部分,并且所有步骤都指向 View 模型中的同一模型/实体。
  • 为了强调绑定(bind)的发布/订阅性质所发生的情况:
    • 用户输入也会在页面底部转发。
    • 表单标题是动态的,“步骤”也是动态的
    • ko.compulated 用于“计算”全名以及是否还有任何“步骤”需要执行
  • 特定于 knockout :请注意该位置周围弹出的括号。如果您选择学习 knockout ,这有时可能会让您感到困惑。它只是意味着您正在评估绑定(bind)容器以获取值。

查看模型

<div>
    <h3 data-bind="text: currentStep().name"></h3>
    <div data-bind="template: { name: 'wizard-step1' }, visible: currentStep().id === 0"></div>
    <div data-bind="template: { name: 'wizard-step2' }, visible: currentStep().id === 1"></div>
    <div data-bind="template: { name: 'wizard-step3' }, visible: currentStep().id === 2"></div>
    <input type="button" value="Next step" data-bind="click: onNext, visible: hasNextSteps" />
    <input type="button" value="Submit" data-bind="click: onSubmit,visible: !hasNextSteps()" />
    <div data-bind="visible: submitResultMessage, text: submitResultMessage"></div>
</div>

<div>
    <h3>Your inputs</h3>
    <div data-bind="visible: questions.fullName">Full name: <span data-bind="text: questions.fullName"></span></div>
    <div data-bind="visible: questions.age">Age:  <span data-bind="text: questions.age"></span>
    </div>
    <div data-bind="visible: questions.favouriteColour">Favourite colour:  <span data-bind="text: questions.favouriteColour"></span>
    </div>
</div>

<script type="text/html" id="wizard-step1">
    <div>
        First name: <input data-bind="value: questions.firstName, valueUpdate:'afterkeydown'" />
    </div>
    <div>
        Last name: <input data-bind="value: questions.lastName, valueUpdate:'afterkeydown'" />
    </div>
</script>

<script type="text/html" id="wizard-step2">
    <div>
        Age: <input data-bind="value: questions.age, valueUpdate:'afterkeydown'" />
    </div>   
</script>

<script type="text/html" id="wizard-step3">
    <div>
        Favourite colour: <input data-bind="value: questions.favouriteColour, valueUpdate:'afterkeydown'" />
    </div>   
</script>

查看

// Entity for holding form data.
var FormData = function() {
  var self = this;

    self.firstName = ko.observable("");
    self.lastName = ko.observable("");
    self.age = ko.observable("");
    self.favouriteColour = ko.observable("");

    self.fullName = ko.computed(function() {        
        if (!self.firstName() && !self.lastName()) {
            return "";
        }

       return self.firstName() + " " + self.lastName(); 
    });
}

// Quick handling for managing steps of the wizard
var wizardSteps = [
    { id: 0, name: "Wizard step 1"},
    { id: 1, name: "More questions"},
    { id: 2, name: "Last step"}
    ];

var ViewModel = function() {
    var self = this;

    // Properties
    self.questions = new FormData();

    self.currentStep = ko.observable(wizardSteps[0]);

    self.submitResultMessage = ko.observable();

    // Actions
    self.onNext = function() {
        var currentIndex = self.currentStep().id;

        if (self.hasNextSteps()) {
            // Move forward one step on the wizard
            self.currentStep(wizardSteps[currentIndex + 1]);
        }
    };

    self.onSubmit = function() {

        self.submitResultMessage("Data is now submitted ");
    };

    // Page control
    self.hasNextSteps = ko.computed(function() {
        var currentIndex = self.currentStep().id;

        return currentIndex < wizardSteps.length - 1;
    });

};

ko.applyBindings(new ViewModel());

关于javascript - 操作 DOM 时的数据绑定(bind)不适用于 Angular、Knockout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22164737/

相关文章:

jquery - 如何打开垂直下拉菜单项以左对齐

javascript - AngularJS ng-repeat 键值对指令

javascript - 测试输入是否只有阿拉伯字符

javascript - jQuery 切换运行两次

javascript - 如何将数字四舍五入到小数点后两位? javascript

javascript - Highcharts 区域填充

angularjs - 如何在指令中使用/同步 Controller 的数据?

html - 如何停止在最后显示的元素上重复 ng-repeat?

javascript - 手动 slider 不应在透明区域可见

javascript - 获取 "TypeError: $(...).css(...) is undefined"尽管使用 if 语句过滤掉所有未定义