问题

  之前有了解过knockout,学习过绑定语法,结合帮助文档,做个Demo倒也不成问题,但是部分地方很不爽,不知道是我的用法不对,还是功力不够。

  比如说,标签里定义的data-bind属性名,必须在调用 ko.applyBindings(viewModel) 前必须定义。而结合具体的示例来看,html有如下代码:

    用户名:<label data-bind="text:userName"></label>
姓名:<label data-bind="text:realName"></label>
毕业院校:<select data-bind="
options:school,
optionsText:'schoolName',
optionsValue:'schoolID',
value:bySchool,
optionsCaption:'请选择'
"></select>

  初步写法则是:

    var viewModel = 
{
userName: ko.observable(),
realName: ko.observable(),
value: ko.observable(),
options: ko.observableArray()
}
ko.applyBindings(viewModel);
//后面ajax操作来修改viewModel
setTimeout(function () {
//加载可选择院校
var school = [{ schoolID: 1, schoolName: "清华大学" },
{ schoolID: 2, schoolName: "北京大学" },
{ schoolID: 3, schoolName: "复旦大学" }
];
viewModel.school(school);
//加载用户信息
var user = {
userName: 'codealone',
realName: '冲动',
bySchool: 1
};
viewModel.userName(user.userName);
viewModel.realName(user.realName);
viewModel.bySchool(user.bySchool);
});

Mapping插件

  写到这,有人可能要跟我说,mapping 插件可以解决这个问题。相关代码如下:

    The time on the server is: <span data-bind='text: serverTime'></span>
and <span data-bind='text: numUsers'></span>user(s) are connected.
<script type="text/javascript">
var data = { serverTime: '2010-01-07', numUsers: 3 };
var viewModel = {};
viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);
</script>

  这样的确是可以解决,可是问题是,我的数据是ajax加载的呀。那么要先定义属性,于是修改后的代码则是:

    The time on the server is: <span data-bind='text: serverTime'></span>
and <span data-bind='text: numUsers'></span>user(s) are connected.
<script type="text/javascript">
var viewModel = {};
viewModel.serverTime = ko.observable();
viewModel.numUsers = ko.observable();
ko.applyBindings(viewModel);
setTimeout(function () { //模拟ajax取数据
var data = { serverTime: '2010-01-07', numUsers: 3 };
ko.mapping.fromJS(data, viewModel);
document.title = "方法已执行";
}, 1000);
</script>

  看起来很好,不过直到数据并没有更新。只有先在初始化之前mapping一次,后面才可以直接更改。

    The time on the server is: <span data-bind='text: serverTime'></span>
and <span data-bind='text: numUsers'></span>user(s) are connected.
<script type="text/javascript">
var data = { serverTime: '', numUsers: '' };
var viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);
setTimeout(function () { //模拟ajax取数据
var data = { serverTime: '2010-01-07', numUsers: 3 };
ko.mapping.fromJS(data, viewModel);
document.title = "方法已执行";
}, 1000);
</script>

  这样的话,就没有问题的,但是这种写法让我很郁闷的是,难不成,我要把事先用到的数据结构全部先定义出来,然后mapping。

我的半自动Mapping

  后来觉得ko在初始化的时候,去检测每个需要绑定的属性,是否已经定义,如果未定义,则抛出异常,这个逻辑让我很不爽,但是不在初始化的时候定义,ko 根本就不知道需要监控哪些属性的变化,而这些属性到底是对象,还是数组。想到这里,觉得初始化的定义难以避免,就想了个方法,批量注册初始化观察对家和批量注册。实现方式很简单,看源码就可以得知。这里贴一下调用方式,第一行代码中的data参数是为了将批量注册的属性名存下来,便于后面直接取出这几个属性的值。

    ko.mapper.observable(viewModel, ['userName', 'realName', 'bySchool'], 'data');
ko.mapper.observableArray(viewModel, ['school']);

  以上操作则是完成了初始化,那么后面的赋值如何批量来进行呢,调用方式如下:

        //加载可选择院校
var school = [{ schoolID: 1, schoolName: "清华大学" },
{ schoolID: 2, schoolName: "北京大学" },
{ schoolID: 3, schoolName: "复旦大学" }
];
ko.mapper.extend(viewModel, {
school: school
});
//加载用户信息
var users = {
userName: 'codealone',
realName: '冲动',
bySchool: 1
};
ko.mapper.extend(viewModel, users);

  第一个extend,最终执行了 viewModel.school(school);

  第二个extend,最终执行了viewModel.userName(users.UserName),viewModel.realName(users.realName);等。

  这样算是完成了一种mapping。

  再说说说刚刚的data参数问题,data参数是为了将属性保存下来,便于后面取出这些属性的值。Ko的取值是这样的,拿上面的viewModel来说,定义了userName,realName,bySchool,那么取值方式则是viewModel.userName(),viewModel.realName(),viewModel.bySchool() ...

        //读取页面上的用户信息
var userInfo = ko.mapper.getValue(viewModel, 'data');
var userInfo2 = ko.mapper.getValue(viewModel, ['userName', 'realName', 'bySchool']);

  这样得到的数据则为:

  {

    userName:'xxxx',

    realName:'xxxxxx',

    bySchool:1

  }

完整示例

  完整页面代码如下:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="../knockout-3.0.0.debug.js"></script>
<script src="../knockout.mapper.js"></script> </head>
<body>
用户名:<label data-bind="text:userName"></label>
姓名:<label data-bind="text:realName"></label>
毕业院校:<select data-bind="
options:school,
optionsText:'schoolName',
optionsValue:'schoolID',
value:bySchool,
optionsCaption:'请选择'
"></select>
</body>
</html>
<script type="text/ecmascript">
//半自动Mapping
var viewModel = {};
ko.mapper.observable(viewModel, ['userName', 'realName', 'bySchool'], 'data');
ko.mapper.observableArray(viewModel, ['school']);
ko.applyBindings(viewModel);
//所有的数据都是基于ajax读取的,这里使用setTimeout进行模拟
setTimeout(function () {
//加载可选择院校
var school = [{ schoolID: 1, schoolName: "清华大学" },
{ schoolID: 2, schoolName: "北京大学" },
{ schoolID: 3, schoolName: "复旦大学" }
];
ko.mapper.extend(viewModel, {
school: school
});
//加载用户信息
var users = {
userName: 'codealone',
realName: '冲动',
bySchool: 1
};
ko.mapper.extend(viewModel, users);
//读取页面上的用户信息
var userInfo = ko.mapper.getValue(viewModel, 'data');
var userInfo2 = ko.mapper.getValue(viewModel, ['userName', 'realName', 'bySchool']);
}, 1000);
</script>

完整的半自动Mapping页面

  测试代码下载

  希望能对于ajax加载的数据结构有更好的解决方案。

knockout 表单绑定 要怎么Mapping才好的更多相关文章

  1. Knockout学习之表单绑定器(上)

    表单绑定器 “click”绑定 Click 绑定器可以将javascript函数绑定到指定的dom元素,并且再该元素被点击时将触发绑定的函数,大多数情况下都会使用button.input和a元素,当然 ...

  2. vue -- v-model 表单绑定

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Vue表单绑定(单选按钮,选择框(单选时,多选时,用 v-for 渲染的动态选项)

    <!DOCTYPE html><html>    <head>        <meta charset="utf-8">      ...

  4. Spirng MVC +Velocity 表单绑定命令对象

    通常,表单中的数据在提交之后可以通过Spring MVC的@RequestParam注解在控制器函数的参数列表中中提取出来,但是一旦表单数据过多的话,参数列表将会变得非常长,最好的解决方案是将表单中的 ...

  5. vue基础-动态样式&表单绑定&vue响应式原理

    动态样式 作用:使用声明式变量来控制class和style的值 语法: :class/:style 注意:尽可能不要把动态class和静态class一起使用,原因动态class起作用的时间会比较晚,需 ...

  6. Knockout学习之表单绑定器(下)

    “hasFocus”绑定 hasFocus绑定器会将DOM元素的焦点状态与视图模型中的属性相关联,当你设置视图模型中关联的属性为true或false后,将能够设置关键的DOM元素是否获得焦点. 比如下 ...

  7. (四)Knockout 表单

    click <div> You've clicked <span data-bind="text: numberOfClicks"></span> ...

  8. KnockoutJS 3.X API 第四章 表单绑定(10) textInput、hasFocus、checked绑定

    textInput绑定目的 textInput绑定主要用于<input>或者<textarea>元素.他提供了DOM和viewmodel的双向更新.不同于value绑定,tex ...

  9. vue form表单绑定事件与方法

    使用v-on绑定事件 <button @click="hello">Hello</button><br /> <button @click ...

随机推荐

  1. 財務会計管理(FI&CO)

    FI(財務会計)系のSAP DBテーブル.随時更新していきます. [勘定コードマスタ]SKA1: 勘定コードマスタ(勘定コード表データ)SKB1: 勘定コードマスタ(会社コードデータ)SKAT: テキ ...

  2. 全方位认识HDMI接口技术

    HDMI接口并不是一个开放的标准.制造商必须向HDMI标准制定协会支付版税,来换取一个生产许可证.不过这个版税可不便宜,每年要交纳15000美元的许可费,并且更黑的是每生产一个HDMI接口就要支付0. ...

  3. AD高级规则设置

    inpolygon 是所有的覆铜 ispad 是焊盘到焊盘的间距 IsVia 过孔间距 ispad and InComponent('S1')    设置某个器件的焊盘间距规则 ispad and H ...

  4. 从键盘输入数,输出它们的平方值&判断是不是2的阶次方数

    1.从键盘输入两个整数,然后输出它们的平方值和立方值 在Java中,没有像C语言那样有一个专供接受键盘输入值的scanf函数,所以一般的做法是从键盘输入一行字符,保存到字符串s中,再将字符组成的字符串 ...

  5. Eclipse 创建 Java 类---Eclipse教程第10课

    打开新建 Java 类向导 你可以使用新建 Java 类向导来创建 Java 类,可以通过以下途径打开 Java 类向导: 点击 "File" 菜单并选择 New > Cla ...

  6. linux下解压命令大全[转]

    本文是复制大神的博文, 供自己参考. 原文出处:http://www.cnblogs.com/eoiioe/archive/2008/09/20/1294681.html .tar 解包:tar xv ...

  7. USACO Section1.3 Ski Course Design 解题报告

    skidesign解题报告 —— icedream61 博客园(转载请注明出处)------------------------------------------------------------ ...

  8. Percona-Tookit工具包之pt-slave-find

      Preface       If we want to check out how many slaves in our replication environment.We can execut ...

  9. os--留

    os.path.abspath(path) #返回绝对路径    绝对路径和文件路径的区别,绝对路径是当前在操作文本的路径,文件路径是当前文本的文件的路径 os.path.basename(path) ...

  10. 解决使用Oracle数据库,项目启动由于表原因无法成功启动问题

    1.仔细看异常信息,如果出现一个  翻译过来是 不仅仅这一张表,那就说明,在连接数据库,定位到表的时候有多张表,不知道连哪一张. 原因: 有多个用户,这两个用户下有相同的表. 就算是在不同的表空间也不 ...