zoukankan      html  css  js  c++  java
  • KnockoutJs学习笔记(一)

    由于工作需要,接触到了Knockout,但是之前对于前台开发真的是不太了解,只能是摸着石头过河,边学边实践了。

    Knockout的官方网站是:http://knockoutjs.com/。我也是跟着官网上的文档一步步学习。

    本篇文章中的测试主要就是依据官网文档中的Creating view models with observables部分来进行的。

    首先,我依照创建view model的方式,在js文件中创建了自己的view model:

    1 var myViewModel = {
    2     name: "Yuki Nagato",
    3     age: 15
    4 };

    随后在相应的html文件中写了些简短的测试段落:

    1 <body>
    2 <h3>My test for knockoutJs(I don't know if it is right to write like this, haha)</h3>
    3 <p>Test start:<span data-bind="text: name"></span></p>
    4 </body>

    此时如果直接在浏览器中浏览html文件的话是不会看到任何结果的,还需要激活Knockout,按照官网的说法,就是Activating Knockout,于是在js文件后又添加了新的一行:

    1 ko.applyBindings(myViewModel);

    嗯,由于博主对于js的知识了解的真的很少,此时就直接想在浏览器中看到效果,结果页面显示如下:

    而chrome的developer tools中显示:

    于是在stackoverflow中找到了相应的问题,发现是这样一个问题:

    提问者在这里采用的是在html文件中的script元素内添加defer属性的方式,这种属性我之前并没有见过,可以留作以后研究,但是另一种解决方式似乎更具有普遍性。现在jQuery的使用频率很高,jQuery中的ready部分详细描述了在使用jQuery的同时解决这种DOM与script载入顺序的方法,具体的文档在http://api.jquery.com/ready/。ready的作用在于指定相应的javascript function在DOM完全载入成功以后执行,javascript中似乎提供的是load事件,可以留作以后研究

    按照文档中的描述,有三种编写方式:

    • $( document ).ready( handler )
    • $().ready( handler ) (这种方式不推荐)
    • $( handler )

    显然第三种方式最为简便,所以通用性也更强,一般的格式如下:

    1 $(function() {
    2     // Handler for .ready() called.
    3 });

    当然,文档中还提到了onload属性和ready的兼容性问题以及jQuery的命名空间问题,由于不涉及我现在要用的东西,可以留作以后研究

    这样一来,我的js文件就变成了这样:

    1 $(function() {
    2     var myViewModel = {
    3     name: "Yuki Nagato",
    4     age: 15
    5     };
    6 
    7     ko.applyBindings(myViewModel);
    8 });

    当然,我也在html文件中添加了jQuery文件的链接,而浏览器中也成功显示出了view model中的name属性:

    而在Knockout的文档中也提到说ko.applyBindings这个函数的参数可以有两个,第一个用于声明你用来激活declarative bingdings的view model,第二个则可以通过指定相应的selector来选择性的绑定view model,这里我做了一个测试,将html文件改成这样:

    1 <p>Name: <span id="name" data-bind="text: name"></span></p>
    2 <p>Age: <span data-bind="text: age"></span></p>

    js文件则改成了这样:

    1 ko.applyBindings(myViewModel, document.getElementById("name"));

    随后页面显示如下:

    可以看到,我们仅仅激活了相应ID的元素,不知道选取DOM node能不能通过jQuery的方式,应该会更为简便一些

    之前的例子里,我仅仅是在页面中展现了view model的属性,但KO的关键优势就在于它能够根据view model的变化来自动更新UI(页面)的变化。为了能让KO知晓view model的变化,我们需要在view model中将相应的属性声明为observable,它是一种特殊的能够通知订阅者相应的改变,并能够自动探测相应的依赖关系的javascript object。于是,我的js文件更新如下:

    1 $(function() {
    2     var myViewModel = {
    3     name: ko.observable("Yuki Nagato"),
    4     age: ko.observable(15)
    5     };
    6 
    7     ko.applyBindings(myViewModel);
    8 });

    而获取或是修改observable的值也是极为方便的,在js文件中添加如下几行:

    1 myViewModel.age(20);
    2 var name = myViewModel.name();
    3 $("#getValueOfOB").text(name);

    在html文件中再添加一个p元素:

    1 <p>Test for getting the value of observable: <span id="getValueOfOB"></span></p>

    这是可以在页面中看到相应的效果:

    可以看出js中对view model修改的代码与applybindings之间的顺序没有没什么关系,在其之前其之后都可行。同时也可以采用链式语法来修改多个view model属性:

    1 myViewModel.name("Kazusa Touma").age(16);

    当然,也可以自己定义相应的function来响应observable的变化,最简单的例子如下:

    1 myViewModel.name.subscribe(function(newName) {
    2   alert("The new name is " + newName);
    3 });
    4 myViewModel.name("Chiaki Izumi"););

     

    需要注意的是,对相应observable的修改应当在自定义的subscribe function之后出现。而subscribe function可以接受三个参数,第一个是callback,作为observable改变时的相应处理;第二个是target(optional),可以指定callback function中的"this"的值;第三个是event(optional, default is "change"),作为callback function所需要响应的事件类型。

    比如,我们可以将event更改为"beforeChange",即在observable更改之前进行自定义的操作,代码和页面显示如下:

    1 var mySubscription = myViewModel.name.subscribe(function(oldName) {
    2   alert("The old name is " + oldName);
    3 }, null, "beforeChange");

    当然,我们自己也可以终止自定义的subscription:

    1 var mySubscription = myViewModel.name.subscribe(function(newName) {
    2   alert("The new name is " + newName);
    3 });
    4 mySubscription.dispose();

    这样一来,之后对observable的修改并不会触发我们自定义的subscribe function。

    最后,该部分的文档也提到说我们可以强制订阅observable相应的改变(即便新的值和原先的值一样也会提醒),为了测试这一功能,我采用了自定义的subscribe function:

     1 var myBeforeSubscription = myViewModel.name.subscribe(function(oldName) {
     2   alert("The old name is " + oldName);
     3 }, null, "beforeChange");
     4 
     5 var mySubscription = myViewModel.name.subscribe(function(newName) {
     6   alert("The new name is " + newName);
     7 });
     8 
     9 myViewModel.name.extend({ notify: "always" });
    10 
    11 myViewModel.name("Kazusa Touma");

    我们可以看到页面产生这样的结果:

    另外,通过extend方法,我们也可以为订阅设定一个延时:

    1 myViewModel.name.extend({ rateLimit: 5000 });

    需要注意的是,这个延时是更改的延时,也就是将view model同步到UI的时间上的延时,而对于针对"beforeChange"事件的自定义subscribe function,它们会直接触发(不会涉及延时)。比如说我将延时设置为5秒,并且设定了两个自定义的subscribe function,一个的event是"beforeChange",另一个event是默认的"change",在页面载入后,beforeChange的function会直接执行,而change的function则会在5秒之后执行。

  • 相关阅读:
    Codeforces Beta Round #92 (Div. 2 Only) B. Permutations 模拟
    POJ 3281 Dining 最大流 Dinic算法
    POJ 2441 Arrange the BUlls 状压DP
    URAL 1152 Faise Mirrors 状压DP 简单题
    URAL 1039 Anniversary Party 树形DP 水题
    URAL 1018 Binary Apple Tree 树形DP 好题 经典
    pytorch中的forward前向传播机制
    .data()与.detach()的区别
    Argparse模块
    pytorch代码调试工具
  • 原文地址:https://www.cnblogs.com/charlieyuki/p/3926858.html
Copyright © 2011-2022 走看看