<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      前端開發框架Bootstrap和KnockoutJS

      江湖中那場異常慘烈的廝殺,如今都快被人遺忘了。當年,所有的武林同道為了同一個敵人都拼盡了全力,為數不多的幸存者心灰意冷,隱姓埋名,遠赴他鄉,他們將唯一的希望寄托給時間。少年子弟江湖老,紅顏少女的鬢邊也有了白發。多年以后,聽聞那個魔頭也不久于人世,他們欣欣然回鄉,卻發現當初殫精竭慮研究出來對付敵人的招數全無用處,曾經受人尊敬的大俠現在被稱為——新手 or 菜鳥。月下小酌,孤獨的他們對著夜空舉起酒杯,吼一聲:“走你,IE6!”

      -----------------------------------------------------割--------------------------------------------------------------------

      Bootstrap是一個前端框架,解放Web開發者的好東東,展現出的UI非常高端大氣上檔次,理論上可以不用寫一行css。只要在標簽中加上合適的屬性即可。請參看Bootstrap中文文檔,這是3.0版本。

      KnockoutJS是一個JavaScript實現的MVVM框架。非常棒。比如列表數據項增減后,不需要重新刷新整個控件片段或自己寫JS增刪節點,只要預先定義模板和符合其語法定義的屬性即可。簡單的說,我們只需要關注數據的存取。官網文檔

      Bootstrap負責UI,KnockoutJS負責數據綁定,兩者相得益彰,Web前端必備利器。

      我們來做一個簡單的例子展示一下它們的威力。

      要擱以前,實現類似功能,可以有兩個選擇:a)直接操作DOM,夠喝一壺,一般喜歡展現技術同學的首選;b)借助各種拉風的重量級JS框架,比如extjs,使用它們的API以減少工作量,不過這些框架的學習曲線也挺扭曲。當然本文所說的兩個框架也涉及到各自的JS類庫,but,提供給開發人員的使用方式是完全不同的,后者更松散(廢話,兩個當然比一個松散)、靈活,且是基于特性聲明的方式,個人表示相當不錯。下面就讓我們開始碼吧。

      首先搭個初步的框架:

      <div id="divAuthManage" class="row" style="margin-top: 30px;">
          <div class="col-md-4 col-sm-4 col-xs-6">
              <div>
                  <div class="input-group">
                      <span class="input-group-addon">用戶名</span>
                      <input id="inputUserName" type="text" class="form-control" />
                      <span class="btn btn-primary input-group-btn">添加</span>
                  </div>
                  <div id="divWaring" class="alert alert-warning" style="display: none;"></div>
              </div>
              <table class="table table-bordered table-hover" style="margin-top: 20px;">
                  <thead>
                      <tr>
                          <th>用戶ID</th>
                          <th>用戶名</th>
                          <th style="text-align: center;">刪除</th>
                      </tr>
                  </thead>
                  <tbody>
                  </tbody>
              </table>
          </div>
          <div class="col-md-8 col-sm-8 col-xs-12">
              @foreach (AreaElement area in Model.Areas)
              {
                  <div class="panel panel-default">
                      <div class="panel-heading">
      
                          @{if (area.Sites.Count == 0)
                            {
                              <label class="checkbox">
                                  <input type="checkbox" value="@area.Code" />
                                  @area.Name
                              </label>
                            }
                            else
                            {
                              @area.Name
                            }
                          }
      
                      </div>
                      @if (area.Sites.Count > 0)
                      {
                          <div class="panel-body">
                              @foreach (SiteElement site in area.Sites)
                              {
                                  <label class="checkbox-inline">
                                      <input type="checkbox" value="@site.Code" />@site.Name
                                  </label>
                              }
                          </div>
                      }
                  </div>
              }
              <p class="text-right">
                  <button type="button" class="btn btn-default">保存</button>
              </p>
          </div>
      </div>

      這里就用到了bootstrap,如果一個元素使用了相應的class,它就會呈現bootstrap中預定義的樣式。bootstrap還提供了data-xxx屬性,這是用來以聲明方式使用組件,這里沒有涉及。now,界面如下:

      圖中標注了需要改進的兩個地方,此時先不考慮。我們現在要先把數據從后臺取出,以及其它的一些操作,于是引進KnockoutJS。接觸過WPF的都知道ViewModel的概念,說白了就是將前端分為UI和交互邏輯,ViewModel就負責交互邏輯,knockoutJS也有這個東西。結合例子具體來看:

      window.adApp.authManageViewModel = (function (ko) {
          var userList = ko.observableArray(),
              error = ko.observable(),
              addUser = function (username) {
                  this.clearError();
                  if (!username) {
                      error("請輸入用戶名.");
                  }
                  else {
                      this._ajaxRequest("post", '/api/UserAuthority/AddUser', { "": username }, function (data) {
                          if (!data.IsSucceed)
                              this.error(data.Message);
                          else {
                              var user = new User(data.Data);
                              this.userList.unshift(user);
                          }
                      });
                  }
              },
              deleteUser = function (user) {
                  this._ajaxRequest("delete", '/api/UserAuthority/DeleteUser', { "": user.userid }, function (data) {
                      if (!data.IsSucceed)
                          this.error(data.Message);
                      else {
                          this.userList.remove(user);
                      }
                  });
              },
              getUsers = function () {
                  this._ajaxRequest("get", '/api/UserAuthority/GetUsers', null, function (data) {
                      this.userList.removeAll();
                      for (var i = 0; i < data.length; i++) {
                          userList.push(new User(data[i]));
                      }
                  });
              },
              selectUser = function (user) {
                  for (var i = 0; i < userList().length; i++) {
                      userList()[i].selected(false);
                  }
                  user.selected(true);
                  this._ajaxRequest("get", '/api/UserAuthority/GetAccessNavItems', { userid: user.userid }, function (data) {
                      user.navitems.removeAll();
                      for (var i = 0; i < data.length; i++) {
                          user.navitems.push(data[i]);
                      }
                  });
              },
              clearError = function () { error(""); };
      
          var viewmodel = {
              userList: userList,
              error: error,
              _ajaxRequest: ajaxRequest,
              addUser: addUser,
              deleteUser: deleteUser,
              clearError: clearError,
              _getUsers: getUsers,
              selectUser: selectUser,
              currentUser: ko.computed(function () {
                  for (var i = 0; i < userList().length; i++) {
                      if (userList()[i].selected()) {
                          return userList()[i];
                      }
                  }
                  return null;
              })
          };
          viewmodel._getUsers();
          return viewmodel;
      
          function ajaxRequest(type, url, data, callback) { // Ajax helper
              this.clearError();
              $.ajax({
                  url: url,
                  data: data,
                  type: type,
                  dataType: "json",
                  context: this,//指定this為當前對象viewmodel
                  success: callback,
                  error: function () {
                      this.error("服務器錯誤.");
                  }
              });
          }
      })(ko);
      
      // Initiate the Knockout bindings
      ko.applyBindings(window.adApp.authManageViewModel);

      window.adApp.authManageViewModel就是ViewModel,它包含了兩個屬性(UserList為用戶集合,error為提示信息,準確的命名應該類似msg,懶得改了)和若干函數(和服務端交互)。ko.applyBindings將該ViewModel綁定到頁面。上述代碼還涉及到兩個類型:

      function NavItem(data) {
          var self = this;
          data = data || {};
      
          // Persisted properties
          self.code = data.code;
          self.name = data.name;
      }
      
      function User(data) {
          var self = this;
          data = data || {};
      
          // Persisted properties
          self.userid = data.userid;
          self.username = data.username;
          data.navitems = data.navitems || [];
          self.navitems = ko.observableArray(data.navitems);
      
          self.selected = ko.observable(false);
      }
      User.prototype.updateNavs = function () {
          var user = this;
          window.adApp.authManageViewModel._ajaxRequest(
              "put", '/api/UserAuthority/UpdateNavItems?userid=' + user.userid, { "": user.navitems()}, function (data) {
                  if (!data.IsSucceed)
                      this.error(data.Message);
                  else {
                      this.error("保存成功!");
                  }
              });
      }

      現在頁面代碼如下:

      <div id="divAuthManage" class="row" style="margin-top: 30px;">
          <div class="col-md-4 col-sm-4 col-xs-6">
              <div>
                  <div class="input-group">
                      <span class="input-group-addon">用戶名</span>
                      @*data-bind="input: clearError" 不支持input綁定,so換用自定義綁定,or采用event綁定如下*@
                      <input id="inputUserName" type="text" class="form-control" data-bind="event: { input: clearError }" />
                      <span class="btn btn-primary input-group-btn" data-bind="click: function (data, event) { addUser(inputUserName.value) }">添加</span>
                  </div>
                  <div id="divWaring" class="alert alert-warning" style="display: none;" data-bind="animVisible: error"></div>
              </div>
              @*如果userList集合有項,才顯示該表格,注意if、ifnot的作用范圍不包括table標記本身,而是從thead開始*@
              <table data-bind="if: userList().length > 0" class="table table-bordered table-hover" style="margin-top: 20px;">
                  <thead>
                      <tr>
                          <th>用戶ID</th>
                          <th>用戶名</th>
                          <th style="text-align: center;">刪除</th>
                      </tr>
                  </thead>
                  <tbody data-bind="foreach: userList">
                      <tr data-bind="css: { success: selected }, click: function (data, event) { $parent.selectUser($data) }">
                          <td><span data-bind="text: userid"></span></td>
                          <td><span data-bind="text: username"></span></td>
                          <td style="text-align: center;">
                              <button type="button" class="btn btn-default btn-xs" data-bind="click: function (data, event) { $parent.deleteUser($data) }, clickBubble: false">
                                  <span class="glyphicon glyphicon-remove"></span>
                              </button>
                          </td>
                      </tr>
                  </tbody>
              </table>
          </div>
          @*將下面div的綁定對象設為currentUser,如果currentUser為空,則該div中的內容不會顯示*@
          <div class="col-md-8 col-sm-8 col-xs-12" data-bind="with: currentUser">
              @foreach (AreaElement area in Model.Areas)
              {
                  <div class="panel panel-default">
                      <div class="panel-heading">
      
                          @{if (area.Sites.Count == 0)
                            {
                              <label class="checkbox">
                                  <input type="checkbox" value="@area.Code" data-bind="checked: navitems" />
                                  @area.Name
                              </label>
                            }
                            else
                            {
                              @area.Name
                            }
                          }
      
                      </div>
                      @if (area.Sites.Count > 0)
                      {
                          <div class="panel-body">
                              @foreach (SiteElement site in area.Sites)
                              {
                                  <label class="checkbox-inline">
                                      <input type="checkbox" value="@site.Code" data-bind="checked: navitems" />@site.Name
                                  </label>
                              }
                          </div>
                      }
                  </div>
              }
              <p class="text-right">
                  <button type="button" class="btn btn-default" data-bind="click: updateNavs">保存</button>
              </p>
          </div>
      </div>

      代碼中加了很多data-bind屬性,作用不言自明。需要注意的是所謂自定義綁定。當綁定的值變動了,希望執行額外的邏輯(和c#中的事件相似),就會用到。這里,當error的值有變動,為空時提示面板隱藏,否則顯示:

      <div id="divWaring" class="alert alert-warning" style="display: none;" data-bind="animVisible: error"></div>

      animVisible就是一個自定義綁定,定義如下:

      ko.bindingHandlers.animVisible = {
          update: function (elem, valueAccessor) {
              var error = ko.unwrap(valueAccessor());
              if (error) {
                  elem.innerText = error;
                  $(elem).show(300);
              }
              else {            
                  $(elem).hide(300);
                  elem.innerText = "";
              }
          }
      };

      OK,接下來,當點擊表格的每一行,currentUser就會自動計算得到(ko.computed),并反饋到界面,綁定了該字段的div內部的相應節點的狀態也會相應變化(checkbox)。保存啥的就不說了。綜上所述,除了必要的與后臺交互的代碼,涉及到操作UI和DOM節點,我們不需要寫一行JS,很爽很舒服。

      ps:本來想寫詳細點,結果發現寫一大堆還不如幾行代碼來的清楚。文中若有錯誤之處,請及時告知,大家交流,共同進步。


      knockoutjs補充:

      1. 若前端元素綁定的是普通屬性(即非observable屬性),雖然屬性值的改變不會反應到前端,但是前端值的改變會改變屬性值;也就是說在這兩種模式下,后端都會監聽前端的相關事件(如input的change事件)
      2. js中直接設置observable屬性值,比如this.ItemData.IsChecked(true);,也將觸發IsChecked.subscribe訂閱的事件,但不會觸發前端dom事件,比如checkbox的change事件
      3. 可以屬性鏈綁定,如<span data-bind="text: BasicInfo.RoleName"></span>

       

      轉載請注明本文出處:http://www.rzrgm.cn/newton/p/3328058.html

      posted @ 2013-09-22 14:40  萊布尼茨  閱讀(15776)  評論(17)    收藏  舉報
      主站蜘蛛池模板: 久久99精品国产99久久6男男| 成人福利国产午夜AV免费不卡在线 | 亚洲天堂av 在线| 亚洲香蕉免费有线视频| 欧美嫩交一区二区三区| 在线日韩日本国产亚洲| 大香伊蕉在人线国产av| 亚洲av一本二本三本| 成人国产精品中文字幕| 私人毛片免费高清影视院| 亚洲欧美牲交| 亚洲av成人无码天堂| 最新国产精品亚洲| 婷婷精品国产亚洲av在线观看 | 国产精品一区二区三区色| 国产成人亚洲综合图区| 国产一区二区三区禁18| 内射中出无码护士在线| 日本欧洲亚洲高清在线| 激情综合色综合啪啪开心| 国产午夜精品久久久久免费视| 朝鲜女子内射杂交bbw| 国产精品视频一区二区三区不卡| 国产精品久久蜜臀av| 亚洲熟妇少妇任你躁在线观看无码| 人妻少妇邻居少妇好多水在线 | 国产愉拍精品手机| 五月婷婷激情视频俺也去淫| 国产精品福利在线观看无码卡一 | 国产区精品福利在线熟女| 在线播放国产精品一品道| 无码精品国产va在线观看| 无码小电影在线观看网站免费| 最新国产精品好看的精品| 一本久久a久久精品综合| 成人av天堂网在线观看| 婷婷四虎东京热无码群交双飞视频| 国产一级二级三级毛片| 樱桃熟了a级毛片| 这里只有精品在线播放| 国产办公室秘书无码精品99|