• 【Knockout.js 学习体验之旅】(2)花式捆绑


    本文是【Knockout.js 学习体验之旅】系列文章的第2篇,所有demo均基于目前knockout.js的最新版本(3.4.0)。小茄才识有限,文中若有不当之处,还望大家指出。

    目录:

          【Knockout.js 学习体验之旅】(1)ko初体验

            【Knockout.js 学习体验之旅】(2)花式捆绑

    Knockout.js 的花式捆绑

    提到捆绑,相信很多邪恶的筒子以为小茄第一时间想到的是:

     罗宾   红色8件套 

    然而,并没有!

    小茄第一时间想到的是 data-bind = "value: price",data-bind = "text: sum",data-bind = "XX: OO"……(好吧,这有点用力过猛了)

    言归正传,在上一篇文章(【Knockoutjs 学习体验之旅】(1)ko初体验)中提到,ko中的 data-bind = "XX:OO"绑定大法除了可以绑定text、value等内容,还可以绑定visible、style等外观属性,也可以绑定click、textInput等各种事件,甚至还能控制程序流程。各种花式捆绑,绝对满足你的幻想。

    下面简单讲讲各种绑定的使用,主要根据被绑定的属性分成表现类、流程类和交互类三种。

    表现类属性

    表现类的绑定属性有visible、text、html、css、style、attr几种,除了css表示css的class之外,其他都很好理解。当然了,style里面的命名要与js一致,要去掉-改成驼峰命名,示范如下:

    <!--HTML code-->
    <div data-bind="visible: shouldShowMessage">You will see this message only when "shouldShowMessage" holds a true value.</div>
    <div>Today's message is: <span data-bind="text: myMessage"></span></div>
    <div data-bind="html: details"></div>
    <div data-bind="css: { profitWarning: currentProfit() < 0 }">CSS class binding test</div>
    <div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }">CSS style binding test</div>
    <a data-bind="attr: { href: url, title: urltitle }">Report</a>
    HTML Code
    // js code
    var viewModel = {
        shouldShowMessage: ko.observable(true),  // Message initially visible
        myMessage: ko.observable(),     // Initially blank
        details: ko.observable(),     // Initially blank
        currentProfit: ko.observable(150000),     // Positive value, so initially we don't apply the "profitWarning" class
        currentProfit: ko.observable(150000),     // Positive value, so initially black
        url: ko.observable("year-end.html"),
        urltitle: ko.observable("Report including final year-end statistics")
    };
    ko.applyBindings(viewModel);     // apply binds
    JS Code

    效果是这样的:

    001

    上一篇文章里面也说过,XXOO里面除了传单个的属性,也可以传JSON对象,也就是说可以组合绑定属性,比如说:

    <!--HTML code-->
    <div data-bind="{visible: shouldShowMessage, text: myMessage, css: { profitWarning: currentProfit() < 0 }}">
        You will see this message only when "shouldShowMessage" holds a true value.
    </div>

    效果当然是这样的:

    002

    表现类的设置比较简单,要注意的一点就是:很多表现类的属性并不需要动态变化,这个时候可以利用viewModel中设置实现数据的集中初始化,但是不要把他们设置成可观察者,如:

    // js code
    var viewModel = {
        shouldShowMessage: ko.observable(true),  // Message initially visible
        myMessage: '这段文字不需要动态更新'     // Initially blank
    };

    流程类属性

    流程类包括foreach、if、ifnot、with和比较高级的"component”绑定,if 和 ifnot 与 visible类似,差别就是:if 会直接从DOM中移除相应的组件,而visible只是控制隐藏显示(注意是增减display: none,而不是CSS里面的visible),组件还是在DOM里面的。with 跟 js 中的 with 也是一样的效果,就是延长了作用域链,简单的来说就是在变量前加了个’前缀.’。这里只介绍一下foreach,component放到和模板绑定一起介绍。

    003

    看看代码:

    <!--HTML code-->
    <p>测试foreach绑定</p>
    <ul data-bind="foreach: people">
    <li>
        No.<span data-bind="text: $index"> </span>
        people's name: <span data-bind="text: name"> </span>
        <a href="#" data-bind="click: $parent.removePeople">RemovePeople</a>
        <a href="#" data-bind="click: remove">Remove</a>
    </li>
    </ul>
    <input type="button" data-bind="click: addPeople" value="Add" />
    HTML Code
    var listModel = function () {
        //设置people数组的值(people实际上是函数数组),使用foreach可以遍历数组对象
        //ul,li对应的是 people和people的子项,所以在li内部绑定时,作用域是在people子项{name……}中,为了调用people外部的removePeople需要用到$parent
        //如果是调用内部的remove,remove中的this为{name……}对应当前li项,作用域为当前域则不用加 $parent。
        this.people = ko.observableArray([
            {name: "Mark Zake", remove: function () {
                that.people.remove(this);    //注意当前对象(就是{name……})和作用域,不用管HTML标签,纯js理解就简单了
            }},
            {name: "James Lebo", remove: function () {
                that.people.remove(this);
            }},
            {name: "Green Deny", remove: function () {
                that.people.remove(this);
            }}
        ]);
    
        //addPeople内部调用了同级people的方法,this会发生改变,应该预先保存this传进去。
        var that = this;
        this.addPeople = function () {
            that.people.push({
                name: new Date().toDateString(),
                remove: function () {
                    that.people.remove(this);
            }});
        };
    
        //remove的对象是整个 li标签,也就是 a标签的父对象。实际上要执行的是 listModel.people.remove(a.parent)
        this.removePeople = function() {
            that.people.remove(this);
        }
    };
    
    ko.applyBindings(new listModel());
    JS Code

    这里比较容易搞混的是DOM节点与ViewModel的层次对应关系。首先,在ul上应用 foreach 绑定,也就是每个 li 对应每个 people 子项。这一点对应上了之后,就按照 js 的作用域规则去理解即可。说到作用域,不得不提 this,正所谓我待this如初恋,this坑我千百遍。这里小茄在官方版本上加了个remove函数,与官方的removePeople对应起来看就简单了。至于$index, $parent这些变量,按字面意思理解即可。

    交互类属性

    终于要到重点了,使用ko的最重要原因就是为了处理动态交互的UI展现问题,这里集中介绍一下与表单相关的一些绑定。

    (1) click绑定

    语法:data-bind="click: clickHandler",这里的clickHandler函数可以是任意函数,并不一定要是ViewModel里的函数,只要能引用到即可。关于click事件有几点需要留意的:

    1. 参数传递,ko默认将当前组件作为第一个参数传给clickHandler函数,这里要注意当前的绑定上下文,比如说在with环境中,传回的组件就会变成with组件而不是你想要的当前组件。如果你还需要传递event参数,则将event作为第二个参数传入。如果还需要传入更多的参数,那么就需要使用一个函数包装起来了。如:

    <button data-bind="click: function(data, event) { myFunction('param1', 'param2', data, event) }">
        Click me
    </button>

    2. 默认行为的设置(比如链接)

    ko默认是禁止默认事件行为的,通常我们为链接绑定点击事件也不会是让其跳转的。不过你如果一定要开启的话,直接在clickHandler里面return true即可。

    3. 冒泡

    ko默认是允许冒泡的,你可以通过 data-bind="click: clickHandler, clickBubble: false"来设置click事件不冒泡。

    (2)event绑定

    ko提供了这个接口让用户自定义绑定事件。关于参数传递、默认行为、冒泡等与click绑定是一样的,使用案例:

    <div>
        <div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails }">
            Mouse over me
        </div>
        <div data-bind="visible: detailsEnabled">
            Details
        </div>
    </div>
    
    <script type="text/javascript">
        var viewModel = {
            detailsEnabled: ko.observable(false),
            enableDetails: function() {
                this.detailsEnabled(true);
            },
            disableDetails: function() {
                this.detailsEnabled(false);
            }
        };
        ko.applyBindings(viewModel);
    </script>
    JS Code

    (3)submit绑定

    主要用来做一些验证表单的工作。ko会阻止默认的提交表单动作,并转入submit绑定的函数中。后续需要提交的时候,在绑定事件中 return true即可。

    PS: 为什么不在表单中使用 click 事件来处理呢?因为 submit 本来就是被设计用来处理提交事件的,它还能接受回车一类的提交动作,但click则不行。

    (4)value 与 textInput 绑定

    在输入框绑定 value 和 textInput 看起来效果差不多,但是更推荐使用 textInput 事件进行绑定,因为 textInput 是新增的专门用来处理输入事件的。在上一篇文章中可以看到,使用 value 绑定时(左)输入之后必须要将焦点从输入框中移出才会进行更新,而 textInput (右)是马上进行更新的。

    screenshot    004

    虽然,value 绑定也可以通过设置 data-bind="{value: price, valueUpdate: 'afterkeydown'}" 实现与 textInput 一样的效果,但是这个在浏览器中的兼容性并不如 textInput 好。

    (5)options绑定(selectedOptions)

    在下拉列表中可使用 options 来绑定子项的值,子项既可以是字符串,也可以是 js 对象。上一篇(【Knockoutjs 学习体验之旅】(1)ko初体验)中展示的是字符串,这次就来传个对象:

    005

    代码:

    <p>Your country:
        <select data-bind="options: availableCountries,
            optionsText: 'countryName',
            value: selectedCountry,
            optionsCaption: 'Choose...'"></select>
    </p>
    <div data-bind="visible: selectedCountry">
        <!-- Appears when you select something -->
        You have chosen a country with population
        <span data-bind="text: selectedCountry() ? selectedCountry().countryPopulation : 'unknown'"></span>.
    </div>
    
    <script type="text/javascript">
        // Constructor for an object with two properties
        var Country = function(name, population) {
            this.countryName = name;
            this.countryPopulation = population;
        };
        var viewModel = {
            availableCountries: ko.observableArray([
                new Country("UK", 65000000),
                new Country("USA", 320000000),
                new Country("Sweden", 29000000)
            ]),
            selectedCountry: ko.observable() // Nothing selected by default
        };
        ko.applyBindings(viewModel);
    </script>
    View Code

    这里使用了option来绑定列表框的选项,使用value绑定选中项目。由于选项是 js 对象,所以要用一个 optionText 来指定在列表框中的展示。optionCaption是指无选中任何项目时候的默认显示值。如果我们设定的是多选列表框的话,那么就不能用 value 来绑定选中项目了,这个时候要用到 selectOptions来绑定选中项目。

    (6)其他绑定:enable/disable, hasFocus , checked , uniqueName。

    这些事件用起来非常简单,就不具体介绍了。最后一个 uniqueName 是用来设置表单控件的唯一 name 属性的,表单中提交到后台时,没有设置 name 属性的值时不会被提交到后台的,所以就有了这么个绑定功能。官网中关于 hasFoucus 还有个比较常用的效果:

    Name:  

    Click the name to edit it; click elsewhere to apply changes.

    点击上面的姓名就可以变成可编辑状态,失去焦点后又变成普通文字,这种效果用ko实现起来相当简单。

    总结

    本篇主要简单介绍了knockoutjs中各种绑定的使用方法,使用这些绑定方法的组合就能简单地做好一个需要较多动态交互的UI页面。使用这些方法比较重要的一点就是要记住绑定的都是函数对象,所以可以直接在HTML里面进行操作,这样的话有时候 js 代码结构可以更简单。

    关于绑定的介绍就到这里了,下一篇再见。码字不易,随手点赞哈~~~

    参考资料:

    1. 官方教程: http://knockoutjs.com/documentation/introduction.html
    2. 汤姆大叔教程(官方教程翻译,版本太旧,信息缺失明显): http://www.cnblogs.com/TomXu/archive/2011/11/21/2257154.html
    3. 深入浅出Knockoutjs: http://www.w2bc.com/Article/25175

    文字较多,惯例凑图!

    原创文章,转载请注明出处!本文链接:http://www.cnblogs.com/qieguo/p/5563254.html 

  • 相关阅读:
    【linux】在命令行里进行数学计算
    vi编辑器的分割窗口
    Linux 磁盘管理命令
    【Matlab】sparse函数和full函数(稀疏矩阵和非稀疏矩阵转换)
    【R】 绘制 热图 heatmap
    Intent用法实例
    Android调用天气预报的WebService简单例子
    Broadcast广播消息
    Android与服务器端数据交互(基于SOAP协议整合android+webservice)
    Java中String类的方法及说明
  • 原文地址:https://www.cnblogs.com/qieguo/p/5563254.html
Copyright © 2020-2023  润新知