使用 Knockout.js 进行 SharePoint Web 部件模板化:第一部分






4.50/5 (4投票s)
如何使用 Knockout.js 框架为 Web 部件进行模板化
引言
这个问题出现在我们收到一个请求,要求创建通用的列表和库 Web 部件,用于显示一些常见的字段,如 ID、标题、描述、文件 URL 等。在此请求之前,我们通过自定义 XSLT 解决了类似的 OOB 列表和库 Web 部件的问题,或者通过创建仅用于品牌化的 Visual Studio Web 部件,或者通过使用 Imtech 内容查询 Web 部件(该 Web 部件本身就是 XSLT 解决方案)。
最终,客户不喜欢 XSLT 解决方案,而我们也不想为每个新的列表或库创建新的 Web 部件。这时 Knockout 就派上用场了。为什么不使用 Knockout 来进行模板化,而不是 XSLT 呢?
我假设阅读本文的读者都了解如何在 SharePoint 中创建 Web 部件、SharePoint 模块、JavaScript 和 HTML,我将不再赘述。
背景
关于 Knockout 的一点介绍
来自 Knockout 网站:“Knockout 是一个 JavaScript 库,可帮助您使用简洁的底层数据模型创建丰富、响应式的显示和编辑器用户界面。”
来自维基百科
Knockout 是一个独立的 JavaScript 实现的 Model-View-ViewModel 模式,并支持模板。因此,其基本原则是:
- 领域数据、视图组件和要显示的数据之间的清晰分离
- 存在一个明确定义的专业代码层来管理视图组件之间的关系
Knockout 包含以下功能:
- 声明式绑定
- 自动 UI 刷新(当数据模型的状态发生变化时,UI 会自动更新)
- 依赖跟踪
- 模板化(使用原生模板引擎,尽管也可以使用其他模板引擎,如 jquery.tmpl)
那么,这里的重点是什么?
首先,您有视图模型 (view model)
var myViewModel = {
personName: 'Bob',
personAge: 123
};
然后,您有视图 (view):
The name is <span data-bind="text:personName"></span>
最后,只需将视图绑定到模型即可
ko.applyBindings(myViewModel);
我们稍后将讨论模型。
使用代码
概念验证
我创建了一个 Web 部件的 HTML 模拟。这很有用,因为我们可以提前准备 JavaScript、CSS 文件、模型和视图,并在没有 SharePoint 和 Visual Studio 的情况下进行测试。
您可以从上面的链接下载概念验证作为单独的下载文件。
参考文献
只需要两个文件引用。
一个是 knockout 库本身
<script type='text/javascript' src="http://knockoutjs.com/downloads/knockout-3.0.0.js"></script>
另一个是我添加到此项目中的 CSS 文件
<link href="css/controls.css" rel="stylesheet" type="text/css" />
模型
我将模型设计为 Item 类。下面是它的样子:
// Item class definition
var Item = function (id, title, datecreated,url,description,thumbnail) {
this.id = id;
this.title = title;
this.datecreated = datecreated;
this.url=url;
this.description=description;
this.thumbnail=thumbnail;
}
它被称为 item,并且有 6 个属性
- id - 项的 ID
- title - 项的标题
- datecreated - 项的创建日期
- url - 项的 URL
- description - 项的描述
- thumbnail - 项的缩略图
视图模型 (View model)
这是视图模型
function viewModel1 (){
var self = this;
self.items = [
new Item(2, 'News1 title','21.10.2013','javascript:OpenDialog(2);'
,'Description News 1','img/pic1.jpg'),
new Item(1, 'News 2 title','21.02.2013','javascript:OpenDialog(1);',
'Description News 2','img/pic2.jpg')
}
视图模型有一个名为 items 的属性,它实际上是 Item 对象的集合。为了模拟目的,我们在该集合中添加了两个 Item 对象(News 1 和 News 2);
视图
这是视图 (View)<div class="glwp glwp-central" id="k1">
<div class="glwpLine"></div>
<h5><img src="PublishingImages/siteIcon.png"
width="28" height="28" align="absmiddle" />
News</h5>
<div class="glwpLineGrey"></div>
<ul data-bind="foreach:items">
<li>
<div class="glwpDate"><span data-bind="text: datecreated" ></span>
<img class="glwpImage" data-bind="attr: { src: thumbnail }" />
</div>
<div class="glwpText glwpText-central" >
<a data-bind="attr: { href: url, title: title }" style="min-height:70px;">
<span class="glwpTextTTL" data-bind="text:title"></span><br />
<span data-bind="text: description"></span>
</a>
</div>
<div class="glwpSep"></div>
</li>
</ul>
</div>
这里有什么
很简单。我们有一个无序列表,它绑定到我们的模型。将为我们 items 集合中的每个项创建一个
属性绑定:
<span data-bind="text: datecreated" ></span>
- 这是最简单的数据绑定。它会将 Item 对象的datecreated
属性写入 span 元素的文本(例如:<span>11/11/2013</span>)<img class="glwpImage" data-bind="attr: { src: thumbnail }" />
。这是一个稍微复杂一些的绑定。它会获取 item 对象的 thumbnail 属性,并将其写入img
元素的src
属性。<a data-bind="attr: { href: url, title: title }" style="min-height:70px;">
。它会将url
属性作为 a 元素的href
属性写入,并将 title 属性作为 title 属性写入。<span class="glwpTextTTL" data-bind="text:title"></span>
。Title 属性将作为 span 元素的文本写入<span data-bind="text: description"></span>
。Description
属性将作为 span 元素的文本写入
因此,任何对 HTML 和 CSS 有 sedikit 了解的人都可以按照自己的喜好自定义此模板,只要提供必需的属性即可。
数据绑定。
ko.applyBindings(viewModel1,document.getElementById('k1'));
注意 applyBindings
方法中的第二个参数。它指定了 document.getElementById('k1')
。我们视图中的第一个 div (<div class="glwp glwp-central" id="k1">) 具有相同的 ID。如果您想在同一页面上拥有多个视图模型,这将非常有用。它会告诉 knockout 将此特定模型 (viewModel1) 绑定到我们页面上的特定模板 (k1)。
我们从中得到了什么?我们将根据此代码创建一个 Web 部件,而此 Web 部件的功能之一是您可以在同一页面上放置相同的 Web 部件多次。这样,就可以在 SharePoint 页面上放置一个 Web 部件来显示新闻,再放置一个 Web 部件来显示项目或文档。它们将共存。
如果您查看源代码,会发现我们有 2 个视图模型(viewModel1 和 viewModel2)和两个模板(k1 和 k2),当然还有两个绑定。一个绑定用于新闻(带有图像和描述),一个绑定用于文件(没有图像,也没有描述)。模板略有不同。
最终结果
这是最终结果

下一步是什么?

您可以下载 (下载 ProofOfConcept.zip) ProofOfConcept.zip,尝试一下,然后继续阅读本系列的第二部分。