本帖最后由 棕榈 于 2020-3-31 18:50 编辑
FineUI + Knockout 实现数据绑定 2
上一篇我基于Knockout实现了基本的数据绑定,这里我将采用Knockout实现FineUI控件的添加及删除,这里的示例只是用于演示,FineUI的Grid完全可以实现示例的效果。
FineUI中控件及布局都是通过JS来实现的,并且都有自己的DOM结构,直接用Knockout基于DOM进行操作是无法实现的,我在原先 knockout-fineui.js 基础上增加一个新的绑定 'ui', 可以直接用它来创建控件,代码:
- <div data-bind="ui:{options:{type:'numberbox',width:100}, value:$data.count}"></div>
复制代码
这里的 options 属性就是创建控件的参数,参数详情可以查看FineUIJS的API文档,后面的 value 与上一篇的数据绑定参数是一致的。这样就可以采用 Knockout中的foreach,if,ifnot等绑定来实现控件添加及删除。
虽然实现了控件的操作,但同时也失去了FineUI中提供的布局功能,由于所生成的控件都是独立于布局容器的,所以也无法通过布局容器进行布局,只能通过CSS来完成相应的布局。但在实际的使用中也发现,采用CSS布局并不是这么容易,由于FineUI的控件都有相应的DOM结构,有时需要进行很多层的样式修改才能完成想要的效果。
所以在常规的使用操作中是不推荐这种方式的,这种方式主要用于一些个性化需求及与其它第三方控件结合使用时采用。
下面为示例代码:
- @page
- @model FineUICore.EmptyProject.RazorPages.Pages.KnockoutModel
- @{
- ViewBag.Title = "Knockout";
- var F = @Html.F();
- }
- @section body {
- <table id="goods" class="table">
- <thead>
- <tr>
- <td scope="col">#</td>
- <td scope="col">名称</td>
- <td scope="col">单位</td>
- <td scope="col">数量</td>
- <td scope="col">单价</td>
- <td scope="col">合计</td>
- <td scope="col">操作</td>
- </tr>
- </thead>
- <tbody>
- <!-- ko foreach: goodsList -->
- <tr>
- <td scope="row"><span data-bind="text:$index()+1"></span></td>
- <td>
- <div data-bind="ui:{options:{type:'dropdownlist',data:$parent.goodsNames,width:100}, value:$data.name}"></div>
- </td>
- <td>
- <div data-bind="ui:{options:{type:'dropdownlist',data:$parent.goodsUnits,width:100}, value:$data.unit}"></div>
- </td>
- <td>
- <div data-bind="ui:{options:{type:'numberbox',width:100}, value:$data.count}"></div>
- </td>
- <td>
- <div data-bind="ui:{options:{type:'numberbox',width:100}, value:$data.unitPrice}"></div>
- </td>
- <td>
- <div data-bind="ui:{options:{type:'label',width:60}, text:'¥'+$data.totalPrice()}"></div>
- </td>
- <td>
- <div data-bind="ui:{options:{type:'button', text:'删除商品'}, click:function(){$parent.goodsList.remove($data)}}"></div>
- </td>
- </tr>
- <!-- /ko -->
- <tr>
- <td colspan="6" style="text-align:right">总价</td>
- <td><span data-bind="text:'¥'+total()"></span></td>
- </tr>
- </tbody>
- </table>
- <f:Panel Title="Knockout" ContentEl="#goods" BodyPadding="15" IsFluid="true">
- <Toolbars>
- <f:Toolbar>
- <Items>
- <f:Button Text="添加商品" AttributeDataTag="f:{click:add}"></f:Button>
- <f:Button Text="生成JSON" AttributeDataTag="f:{click:json}"></f:Button>
- </Items>
- </f:Toolbar>
- </Toolbars>
- </f:Panel>
- <br />
- <h5 data-bind="visible:goodsList().length>0">商品JSON</h5>
- <div data-bind="text:goodsJson,visible:goodsList().length>0"></div>
- }
- @section script {
- <script src="~/knockout-3.5.1/knockout.js"></script>
- <script src="~/res/js/knockout-fineui.js"></script>
- <script>
- F.ready(function () {
- $('[data-tag]').each(function () {
- $(this).attr('data-bind', $(this).data('tag'));
- });
- function Goods() {
- var self = this;
- self.name = ko.observable('1');
- self.unit = ko.observable('1');
- self.count = ko.observable(1);
- self.unitPrice = ko.observable(3450);
- self.totalPrice = ko.pureComputed(function () {
- return self.unitPrice() * self.count();
- });
- };
- function ViewModel() {
- var self = this;
- self.goodsNames = [
- ['1', '台式电脑'],
- ['2', '笔记本'],
- ['3', '硬盘'],
- ['4', '内存条'],
- ['5', '光盘']
- ];
- self.goodsUnits = [
- ['1', '台'],
- ['2', '块'],
- ['3', '条'],
- ['4', '个'],
- ['5', '张']
- ];
- self.goodsList = ko.observableArray();
- self.goodsJson = ko.observable();
- self.total = ko.pureComputed(function () {
- var total = 0;
- for (var goods of self.goodsList()) {
- total += goods.totalPrice();
- }
- return total;
- });
- self.add = function () {
- self.goodsList.push(new Goods());
- }
- self.json = function () {
- self.goodsJson(ko.toJSON(self.goodsList));
- };
- };
- ko.applyBindings(new ViewModel());
- });
- </script>
- }
复制代码
示例项目文件请到知识星球下载
|