Magento 2 - Alan Storm 博客 - KnockoutJS 入门指南

8.38K 浏览翻译

Magento 2 - Alan Storm 博客 - KnockoutJS 入门指南

这是速成课程,意在让工作中的 Magento 开发者熟悉 KnockoutJS 的基本概念,着重于 Magento 用到的功能特点。如果你打算使用 KnockoutJS 构建任何实质性的内容,我们强烈建议通读KnockoutJS 官方教程


初始 Model,View,View Model

最快理解 KnockoutJS 的方法是通过基本例子。首先,让我们来新建下面这个 HTML 页面。

  
      
      
      
  
    
          
     

           

       
        

 这个页面:

  • 从 cloudflare CDN 加载 KnockoutJS 库
  • 从 code CDN 加载 jQuery 库
  • 建立一个空 DOM 节点结构

你没必要一定从 CDN 加载 jQuery 和 KnockoutJS,但这是做对这个教程来说是最简单。如果你在浏览器中加载这个页面,它是完全空白的。那是因为我们需要:

  1. 添加创建一个 view model 的 Javascript 代码,并且应用 KnockoutJS 绑定
  2. 给读取 view model 的 HTML 页面添加 view 代码

解决第一个,我们给页面添加第三个 Javascript 文件。按照以下内容创建一个名为 ko-init.js 的文件。

//File: ko-init.js jQuery(function(){     
viewModel = {         
    title:"Hello World",         
    content:"So many years of hello world" };     
 ko.applyBindings(viewModel); });

并且把 ko-init.js 作为第三个 Javascript 添加到页面中。

 
 
     

最终,改变 h1 和 p 标签以让他们带有 data-bind 属性。

 
     
        
   

 

完成上述操作后,重新加载页面,你应该可以看到渲染后的标题和内容。恭喜你!你刚刚创建了你第一个 KnockoutJS 的 view model 和 view 。


刚发生了什么

KnockoutJS 宣称自己是 “MVVM” 系统,即 Model,View,View Model 。尽管,最好说 KnockoutJS 是一个 VVM 系统。因为它跟用来获取数据的 model 代码跟无关。View 是你的 HTML 页面。View Model 是包含 Javascript 对象。看一下这个 Javascript 代码:

//File: ko-init.js 
jQuery(function(){     
   viewModel = {         
      title:"Hello World",        
      content:"So many years of hello world"};      
   ko.applyBindings(viewModel); 
});

虽然jQuery 不是必须的。但在整个 documen t或者 DOM 加载之前KnockoutJS 不能开始渲染 view ,并且 jQuery 默认的 document ready 功能可以很好的达到这一目的。这里,我们创建了一个简单的键值对的 view model 。

//File: ko-init.js 
viewModel = {     
   title:"Hello World",    
   content:"So many years of hello world" 
};

然后我们应用 KnockoutJS 的绑定。换句话说是我们告诉 KnockoutJS 用 view model 来渲染 view 。在说一次,view 就是 HTML 页面。View 中重要的部分就是 data-bind 属性。

   
     
        
   

 

当你执行 applyBindings ,KnockoutJS 会浏览整个 HTML 页面的 data-bind 属性。当它找到这些属性的时候,它会解析这个属性上以获取 name 和 value ,然后根据绑定的 name 调用一套规则。比如,上面提到的绑定时 text 绑定。我们传入 text 绑定的值是 title 。text 绑定应用的一组规则是“使用传入绑定的 value 来从 view model 对象中获取值,并且把获取的值作为 text 节点添加到页面中”。如果用纯 Javascript 写出来,最终结果是可能是这样的:value = viewModel['title']; textNode = document.createTextNode(value); h1.appendChild(textNode); KnockoutJS 的第一招是让开发者摆脱直接使用 Javascript 来创建和更新 DOM 节点。反而可以写HTML,用 data-bind 属性进行标记,然后只是把值分配给一个对象。你也不要局限于键值对。考虑一下更复杂的 view model 。

jQuery(function(){
     var viewModelConstructor = function()     {         
        this.getTitle = function() { return "Hello Method World";}
        this.content = "So many years of hello world";
     }
     viewModel = new viewModelConstructor;    
     ko.applyBindings(viewModel);
});

这里,我们使用了一个 Javascript 构造函数创建了一个带有 getTitle 方法的简单对象。如果我们改变 view 来调用 getTitle 方法,你会看到它会如你想要的那个:


     
        
   

 

另一种考虑绑定参数的方式是他们是临时的有限的访问 view model 值和方法的 Javascript 作用域。


其他的绑定

虽然这个例子简单,但是你可以开始看到这个基本的构造是如何执行更复杂的视图逻辑的。data-bind 实现了更新 DOM,纯非 DOM 的 Javascript 代码实现了 model 的更新。你将会看到其他的绑定。比如,我们在 viewModelConstructor 添加一个属性 theVaule 。

//File: ko-init.js 
jQuery(function(){
     var viewModelConstructor = function() {         
        this.getTitle = function() {
             return "Hello World";         
        }        
        this.content = "So many years of hello world";                
        this.theValue = "2";     
     }     
     viewModel = new viewModelConstructor;     
     ko.applyBindings(viewModel);         
});

然后,添加一个带有新绑定的 input 标签。

   

          
     

                    

刷新页面,你会看到一个值为 2 的 HTML input 标签:

这里,我们用了一个新的 KnockoutJS 绑定。data-bind="value:theValue"    我们使用 value 这个绑定,将一个值应用于表单字段。接下来,我们把 input 改成 select,并且应用相同的绑定。

   

          
     

                          -- Choose --                        First                        Second                                Third                                   

如果你重新加载页面,你将会看到这个绑定给 select 设置了值。

虽然这个例子简单,但是这背后的概念却不简单。不需要改变任何 Javascript 应用的代码,这个 value 绑定就可以改变 UI 。


Observables

到现在为止,我们所看到的是一个强大的简单的把戏。简洁,也许也很有用,但是它只是给  KnockoutJS 真正的 “重量级”功能 —— observables 奠定了基础。我们将再一次用一个例子开始。按照以下内容改变你的 view :

  

     

                              -- Choose --                             First                             Second                                     Third                                                             
         Do It

按照以下内容改变 view model 和绑定:

//File: ko-init.js 
jQuery(function(){
     var viewModelConstructor = function() {
                this.theValue = ko.observable("1");     
     }     
     window.viewModel = new viewModelConstructor;     
     ko.applyBindings(window.viewModel);         
});

如果重新加载页面,你可以看到我们绑定在 input 和 p 标签上的值。到现在为止,view 没什么新鲜的东西,和之前做到绑定一样。然而,你可能注意到了,在 view model 中有一些不同的。

//File: ko-init.js 
this.theValue = ko.observable("1");

没有给 theValue 设置一个值或者自定义的方法,而是设置了一个 KnockoutJS 叫做 observable 的一个值。Observable 是特殊的,某种程度上是设值函数和取值函数。如果你打开 Javascript 控制台,输入以下内容,你可以通过把它当函数调用来获取 observable 的值(viewModel 在控制台是一个变量,因为我们把定义为 window 对象下的全局对象)

> viewModel.theValue()     
> "1"

我们可以通过传入一个参数给 observable 设置一个值。以下是如果设置和获取 observable 的值:

> viewModel.theValue("3") 
//... 
> viewModel.theValue() 
> "3"

然而,observable 真正的作用是如果作用于绑定了 observable 的 DOM 节点。通过控制台改变 observable 的值,然后观察浏览器:

> viewModel.theValue("3"); 
> viewModel.theValue("2"); 
> viewModel.theValue("1"); 
> viewModel.theValue("10");

当你更新 observable 的值的时候,绑定的节点的值同时也在改变。有一次,作为开发者,我们不用担心 DOM 节点如何更新了,一旦我们在 model 中设置了值,这个值自动反映在用户界面。虽然这个不再本文范围内,但是你仍然可以看到当 view model 中包含函数的时候他们是如何形成复杂的 Javascript 应用的。

//File: ko-init.js 
jQuery(function(){
     var viewModelConstructor = function()     {
                 this.theValue = ko.observable("1");         
                 var that = this;         
                 this.pickRandomValue = function(){
                              var val = Math.floor(Math.random() * (3));             
                              that.theValue(val);         
                  };     
       }     
       window.viewModel = new viewModelConstructor;     
       ko.applyBindings(window.viewModel);         
});

并且,使用 KnockoutJS 的事件绑定,比如 click

   
Do It

把对于这个的解析作为练习留给读者。


模板绑定

另一个对于理解来说很重要的绑定是 KnockoutJS 的模板绑定。想一下有这样的 view model:

//File: ko-init.js 
jQuery(function(){
     var viewModelConstructor = function()     {
                 this.first = {
                              theTitle:ko.observable("Hello World"),             
                              theContent:ko.observable("Back to Hello World")         
                 };         
                 this.second = {
                              theTitle:ko.observable("Goodbye World"),             
                              theContent:ko.observable("We're sailing west now")                     
                 };                 
      }     
      viewModel = new viewModelConstructor;     
      ko.applyBindings(viewModel);         
});

我们创建了一个和数据对象混合在一起的标准的 view model 。如果这样的 view 结合在一起:

  

     
           
                                               

           

你将会看到:

把 Javascript 对象作为模板绑定的参数

  

 这个数据参数是我们想要用来渲染的 view model 的属性。模板的名字 —— 是要找到和渲染的模板的名字。给系统添加命名模板的最基本的方法是添加一个带有 type 是 text/html 的

    如果之前没见过这个,它可能看起来比较奇怪,但是很多现在的 Javascript 框架使用不带 text/javascript 的