easyui的datagrid的使用记录

datagrid是在 table的基础上变化而来的, 而不是在div的基础上来的。 从div来变成 datagrid,样式的设置仍是是比较麻烦的。php

dg=datagrid 的标题 来源于 columns 属性, 其内容 来源于 url属性。 关键是, 必定要设置这样的属性, 才能给你显示标题和内容, 不然即便你写了 tr等都不会显示css

dg的url 最后输出的内容 必须是 json格式: 若是是php的, 则要用echo, 若是是 其余文件,就要用 json数据html

最重要的是: dg的前端 和 后台 服务器之间的 通讯 , 都是 经过 ajax的方式 来 实现的。 若是在 php中 有 sleep语句的话, 会看到 加载loading...等待的效果。 ajax提交动做 发生在 每次你在前台 点击 下一页等按钮的时候, 前台须要在ajax提交的时候, 向后台服务器 传送数据; 后台须要 返回 json格式的 数据 给 前台。

并且ajax的方式好像都是 post方式。
好比: 分页, 前端 须要 向 后台 传递数据: 一个是page(当前页码,便是第几页?), 一个是 pageSize(一页多少条数据)。 而后后台post获取到 页码和页数, 在 mysql的查询语句中 ,用 limit start rowsCount, 来规范限定 返回的数据。
并且, 后台 除了返回 当前页面须要的部分 rows数据外, 还要返回一个 total总页数。
最后的 返回结果 要写成 json格式的: 这种 类型: {"total": $total, "rows": .....}前端

dg的主要内容:

一个是加载 dg的内容, 并完成分页;
二个是, 排序,能够只作 初始化的时候 排序;
三是: 设置dg的样式, 有striped, rowNumbers, singSelected为true等等.mysql

只要是ajax服务器端有echo内容的, 即便在前端没有处理、使用 这些数据的代码,好比没有什么alert的, 也是能够看到服务器返回的数据的, 使用firebug的 network的 param, 和response,就能够查看,并且这个实际上是查看得很详细很全面 的。

关于isset和 empty在 查询按钮使用时的区别?

isset是判断 $_POST的某个 变量名 是否设置了的, 主要是 用来 判断 按钮 是否被 单击了的, 主要是 防止 页面刷新时 执行代码;
而 !empty 是判断 $_POST的变量名的值是否为空, 主要是用来判断搜索框中是否有输入 内容的, 经常使用的判断就是:
if(isset($_POST['name']) && !empty($_POST['name'])){...}ajax

php中变量的两边使用 大括号?

主要有三种情形:sql

  • 一是避免 变量 和变量后面的字符串 连在一块儿 , 从而引发混淆和错误;
  • 二是 在 变量的外面两边 使用 大括号, 能够在 单引号中 也能够输出变量的值, 避免使用 点号来链接 字符串的麻烦
  • 三是, 在 变量的名称后 使用大括号, 好比 $str{5} 能够输出字符串中的 第n 个字符。经常使用来判断字符串的长度:if(!isset($str{5})){...}

==============================================数据库

写代码的一个重要方法, 不是从上到下挨着挨着的写, 而是先写结构, 像if...else这些结构, 而后写简单的分支,最后才写重要的最复杂的分支

  • dg的 增删改 编辑操做, 相似于百度网盘, 工具栏上 各类操做按钮, 而后在一个 obj={...}的各类 成员变量和成员方法中 来实现这些功能.
  • show 和hide方法, 能够同时针对多个 匹配的元素, 好比: 多个按钮 能够同时一次性的 show 或 hide: $('#btn1, #btn2'). show(); $('#btn1, #btn2'). hide();

关于datagrid的主要内容有:

  1. 就是dg的内容载入, 一般是经过js的方式, 而且要分页;
  2. 就是对内容进行 排序, 通常实现初始化的时候排序就行了
  3. 是设置dg的内容的一些样式, 好比: striped, rowNumbers, singleSelect(可是若是要增删改的话, 一般还不能设为单选择), 列宽自适应等fitColmns. 在列宽自适应的时候, 要同时设置每一列的宽度为100(这个100是百分比)
  4. 设置工具栏, 增删改的按钮, 以及 实现查找功能. 工具栏 仍是 使用 id#tb的方式. 查询的时候, 可能有多个查询条件, 使用 And. 还要注意在查询/查找 /过滤的状况下, 分页功能仍然要是正确的和可用的
    要注意查询/ (以及后面的 增删改等操做) 的过程基本上 都是3步走 : 在obj对应的 方法函数中, 先调用 dg的 load方法, 向服务器 传递 查询条件的 键值对; 而后服务器端 接受查询条件,在数据库中进行 处理, 并返回结果; 而后 再在客户端 用 ajax 处理接收到的数据.
  5. 5/6/7章 是进行增删改操做的: 第五章是进行增长操做的 前台处理和数据准备和ajax提交; 第六章是进行删除和修改前台处理和数据准备等; 第七章是讲 增删改的后台服务器操做的

而有些操做是, 共同的: 好比 开始编辑的操做是: beginEdit, 结束编辑的操做是: endEdit.json

==========================================bootstrap

dg的数据加载?

  1. columns属性是 两个中括号, 每一个对象的属性能够有: field, title, checkbox, sortable, width, 数据的对齐方式align/valign, 跨列/行 rowspan, colspan等
  2. 列的内容, 只能从 url属性中 经过 ajax 远程加载, 要注意的是, url的内容, 是一个 json格式的数组, 数组元素是 json格式的对象 . 若是是从数据库取数据, 必须进行json 格式处理.即:
    [{"id": 1, "name": "foo"}, .....] 的形式. 若是 php返回的格式 不是这样的, 将不会加载数据 进来.
    好比
public function  dgcontent(){
    $sort = I('post.sort');
    $order = I('post.order');
    $page = I('post.page');
    $pageSize = I('post.rows');
    $from = $pageSize*($page-1);

    $dg = M('dg');
    $total = $dg -> count();

    $result = $dg->field('id, dept, class, name')->order("$sort $order")->limit($from,$pageSize)->select();
    $json="";
    for($i=0, $j=count($result); $i<$j; $i++){
      $json .= json_encode($result[$i]).',';
    }

    $json ='{"total":'.$total.',"rows":['. substr($json, 0 , -1).']}';
    
    echo $json;
  }

==========================================

strip和stripe的区别?

  • strip [ strip] : 的意思, 名词时表示: 条, 带, 狭长地带, 带子, 布带的意思, 动词, 则是 '剥夺'; '分割成条带"
  • stripe [straip] 的意思 , 是 各类 条纹! 好比 斑马身上的条纹, 横条纹, 竖条纹, 测试压力的复杂条纹之类的.

MySQL按照字段的 汉字的拼音排序,怎么和常规的想象不同啊?

按照汉字的拼音排序,用的比较可能是在人名的排序中,按照姓氏的拼音字母,从A到Z排序; 若是存储姓名的字段采用的是GBK字符集,那就好办了,由于GBK内码编码时自己就采用了拼音排序的方法(经常使用一级汉字3755个采用拼音排序,二级汉字就不是了,但考虑到人名等都是经常使用汉字,所以只是针对一级汉字能正确排序也够用了)。 直接在查询语句后面 添加 order by name asc; 查询结果按照姓氏的升序排序; 若是存储姓名的字段采用的是 utf8字符集,须要在排序的时候对字段进行转码;对于的代码是 order by convert(name using gbk) asc; 一样,查询的结果也是按照姓氏的升序排序(因此, 若是存储的是utf8字符集, 由于有一个转码的过程, 因此看到的排序和想象中的不同.

count(1) 是什么意思?

count(1),其实就是计算一共有多少符合条件的行。
1并非表示第一个字段,而是表示一个固定值。
其实就能够想成表中有这么一个字段,这个字段就是固定值1,count(1),就是计算一共有多少个1.
同理,count(2),也能够,获得的值彻底同样,count('x'),count('y')都是能够的。同样的理解方式。在你这个语句理均可以使用,返回的值彻底是同样的。就是计数。
count(*),执行时会把星号翻译成字段的具体名字,效果也是同样的,不过多了一个翻译的动做,比固定值的方式效率稍微低一些。

=====================================

到底用margin仍是用top?

主要仍是从 语义和你的用途上来区分,虽然都能实现相同的效果。

什么时候应当使用margin: 
- 不须要在border外侧添加空白时。 
- 空白处不须要背景(色)时。 
- 上下相连的两个盒子之间的空白,须要相互抵消时。如15px + 20px的margin,将获得20px的空白。 

什么时候应当时用padding: 
-  须要在border内测添加空白时。 
-  空白处须要背景(色)时。 
-  上下相连的两个盒子之间的空白,但愿等于二者之和时。如15px + 20px的padding,将获得35px的空白。 

::: margin是用来隔开元素与元素的间距;padding是用来隔开元素与内容的间隔。
margin用于布局分开元素使元素与元素互不相干;“老死不相往来” 是两家人

padding用于元素与内容之间的间隔,让内容(文字)与(包裹)元素之间有一段“呼吸距离”。 是一家人

======================================

关于js字面对象的定义:

/*在js中定义变量,并非必须加var的! 并且, 不加var表示的是 "全局变量", 是顶级对象window的成员变量

  • 直接定义的对象字面变量, 不像用function定义的类, 能够用var什么的, {}内部只能是 key: val形式的键值对(无序)集合,因此, 即便是
    定义成员变量, 也只能用 var_name: some_value的形式来定义, 而不能用 分号语句的形式. 同时, 全部的键值对之间 要用 逗号隔开
    */
//这里的obj没有加var, 就是全局对象window的属性

obj={
  rowEdit : undefined,
  search: function(){
  },
  add: function(){
  },
  update: function(){
  },
  remove: function(){
  },
  save:function(){
  },
};

js中的几种 假值和 空值? (参考: https://blog.csdn.net/u012739535/article/details/17621247, https://www.cnblogs.com/yangzhx/p/4019073.html )

包括: undefined, '', 0, null, false. 这些都叫 假值或空值, 在 if判断中都是假. 可是它们仍是有区别的:

  1. 它们的类型不一样: typeof( var_name) 能够知道: undefined 的类型是: undefined, 0 的类型是: number, '' 的类型是string, null的类型是: object, 也就是说 null是对象的空值; false是boolean类型的.
  2. 这些空值相互之间 用 == 判断 , 的结果 是 : 0, false , ''', 三者之间是相等的: 即 0 == false == '' 的结果是true的. 能够认为这三个是 " 假值". 而 undefined==null , 能够认为它们是空值. 可是 undefined和 null 跟 数字相加的结果是不一样的: 好比: 10+null =10, 10+undefined = NaN.
    全部的假值 用 == 和 空值 比较的 结果 都是 false.
    假值 , 有一个实际的对象, 因此 能够用 .toString() 方法.
    而空值, 连对象都没有, 因此 不能用 .toString 方法, 不然将抛出异常

  3. 再就是它们 强制类型转换 : String(var_name) 后的结果不一样: 转换成 字符串的时候, 结果分别 跟它们的 "原型字面字符串". 这在字符串拼接 累加的时候要注意.
  4. undefined表示 无效对象, 当定义一个变量未被初始化时, 就是undefined, 而 null是已经被初始化 为空对象. 可是全部的空值和假值 用 === 判断 都是false.

js中(包括其余任何 面向对象的语言) 都是同样的, 若是 要在对象中, (即对象内部) , 引用对象的成员变量, 都应该 加上对象自己的引用this, 不然凡是不加this的变量, 都认为是全局变量 而不是对象自己的成员变量, 这样就会报引用错误! 固然, 若是是在对象的外部, 引用对象的成员, 就要用对象的类名了, 好比: obj.rowEdit.

obj={
  rowEdit : undefined,
  search: function(){
....

  add: function(){
    if(!this.rowEdit){   // 这里要加this
      $('#save, #cancel').show();
      $('#box').datagrid('insertRow',{
    index: 0, 
    row: { }
      });

datagrid如何禁止编辑某一行, 某一列或某一个 单元格?

参考 : https://www.cnblogs.com/langhua/p/3672820.html

  1. 禁止行编辑: 先获取到某一行, 而后根据条件, 不调用beginEdit方法, 直接返回, 其余则调用 beginEdit方法
  2. 禁止某一列编辑, 要么直接就不用设置 列的 editor属性; 若是设置了editor属性, 则调用 getColumnOption, 返回列的属性op, 而后设置 op.editor={} 为空
  3. 禁止某一个单元格编辑...

=================================================

dg中, tp中, 凡是从控制器传递到 模板的变量, 好比: $this ->foo = 'foo',

  1. 那么在 模板中, {$foo}是能够直接解析的! 根本就不须要 再在 {$foo} 的两边再 考虑什么引号了, 不论是单引号, 仍是 双引号都再也不须要了! 特别是再 href传递变量的时候 加上 引号等 反而会出错. 好比: url: "{:U('xscontent')}"+'/?class={$class}', 就行了.
  2. 可是 , 若是是 在 alert 等 语句中, 要 使用 模板变量的话, 你就仍是须要 加上 引号了, 由于 直接解析模板变量后, 就是 一个 "字符序列", 不是 字符串! 而报错!

dg的后台是如何返回数据, 来填充前台的记录行的?

/*datagrid的返回结果, 来填充 前台的 数据行,必须严格要求json格式, 并且json的格式和属性名必须是: 
     *  "rows:": json_object_array, 即必须是rows, 后面的数据必须是数组, 每一个数组元素必须是json格式的对象
     * echo '{"total":"11","rows":[{"id":"100", "class":"A_class", "name":"the_Name", "account":"the_account"}]}';
     */

==============================================

一个很重要的注意问题: 在ajax中, 若是 url的目标地址, target是空的字符串时, 该次 ajax 将提交给 "当前页面"! 从而也会获得 ajax 成功success的 结果! 而事实上 这在不少应用场景下 是 不容许的. 因此 你要 判断 一下 你的 ajax url 目标地址 是否为空

好比: 在 dg的 onAfterEdit事件中, 就要判断 url 是否为空, 而后才去调用 ajax.

onAfterEdit: function(rowIndex, rowData, changes){  
      var inserted = $('#box').datagrid('getChanges', 'inserted');
      var updated = $('#box').datagrid('getChanges', 'updated');
      var url=info='';
      if(inserted.length>0){
    url='{:U("add")}';
    info='新增';
      }
      if(updated.length>0){
    url='{:U("update")}';
    info='修改';
      }

/*
     这里很重要 , 要判断一下 url是否为空, 不然 即便任意地 双击 一行记录, 再去 双击另一行记录, 即便没有和数据库进行 修改操做, 也会提示 ajax的success提示信息 , 然而这个时错误的! 
*/
      if(url!='' && info != ''){   
    $.ajax({
    type: 'post',
    url: url,
    data: {row: rowData,},
    beforeSend: function(){
      $('#box').datagrid('loading');
    },
    success: function(data){
      if(data !== false){
        $('#box').datagrid('loaded');
        $('#box').datagrid('load');
        $('#box').datagrid('unselectAll');
        $.messager.show({
          title: '消息',
          msg: '1个班级 '+ info +' 成功', 
          showType: 'slide',
          timeout: 3000
        });
        obj.rowEdit = undefined;
      }
    },
});

===================================================

如何禁用datagrid的某一行被 单击选中或 被 双击选中? 参考: https://blog.csdn.net/Dzq_Boyka/article/details/78531217

主要思想是, 在 onClickRow 和 onDblClickRow 事件中 , 必须显示的调用 $('#box').datagrid('unselectRow', rowIndex)方法, 不能只是 简单地 返回 return.

  1. 要想使dg 在 新增的时候, 不能选择行或 双击行 操做, 那么 能够设置一个 标识变量: isAdded , 当 每次 新增的时候, 都从新设置 isAdded = false, 而后, 判断 onClickRow 和 onDblClickRow 事件中 的 isAdded是否 为false, 或者 true

  2. 可是又要保证 初次载入 datagrid的时候, 若是不点击 新增的时候, 要可以 选择单行, 或 双击单行操做, 就要 初始化 obj的 isAdded 为true.

obj={
  rowEdit : undefined,
  isAdded: true,  // 这里是 关键! 
  add: function(){
    // 一旦增长的时候, 就要从新初始化isAdded为false, 由于只要保存/取消一次后, isAdded就失效了
    this.isAdded=false;

....
}

    onDblClickRow: function(rowIndex, rowData){
       // 在新增记录的时候, 禁止单击选行 和 双击选行

      if(!obj.isAdded){
      $('#box').datagrid('unselectRow', rowIndex);
      return;
      }
     
      // 双击某一行的时候, 首先要关闭以前可能被修改的行
      if(obj.rowEdit != undefined){
    $('#box').datagrid('endEdit', obj.rowEdit);
    obj.rowEdit = undefined;
      }
  ............
    },
    onClickRow: function(rowIndex, rowData){
          if(!obj.isAdded){
      $('#box').datagrid('unselectRow', rowIndex);
      return;
      }
    },

=====================================================

分页器: pagination的ajax事件? 参考: https://blog.csdn.net/H12KJGJ/article/details/53672096

  1. 分页器的分页list , 不是固定的, 也不是什么 倍数, 你能够任意的自由的 设置 任意数值:
pageList     类型array    用法: 用户能改变页面尺寸。pageList 属性定义了能改为多大的尺寸。
代码实例:

    $('#pp').pagination({
        pageList: [10,20,50,100]
    });
  1. 分页器中 的一个 页面 由两个 因素来决定: 一个是: pageSize( 每个页面的最大尺寸), pageNumber(页数), 因此 每一页的第一条数据的索引值就是: pageSize*(pageNumber-1);
    这个就是用来 作 数据库的limit的 依据的:
    所以 : onSelectPage 事件, 就是 当从新改变了pageSize , 从新选择了 pageNumber后所获得的页面.

  2. 总共有4个 ajax事件: onSelectPage, onBeforeRefresh, onRefresh, onChangePageSize... 所以, 在dg中改变分页尺寸的事件是 : onChangePageSize的回调函数中写

===========================================

关于bootstrap中的 table中的单元格内容 水平居中和 垂直居中? 参考: https://blog.csdn.net/peng_hong_fu/article/details/70662979

  1. 水平居中是: 写 text-center类, 而垂直居中, 则是 写 stye的 vertical-align: middle
  2. 要注意的是: th的水平居中, 要写在 th单元格内 , 不能写在th的父元素 tr中; 普通的td的水平居中能够写在父元素 tr中
    而垂直居中 , 不能简单的写: tbody tr td的样式, 而是要 写 .table tbody tr td. 由于后者的 css优先级为 10+1+1+1 =13, 而前者的css优先级是: 1+1+1=3. 因此 要 优先执行 后者的css. 然后者的css正是在 bootstrap中定义的, 默认为top. 因此 你简单的写 tbody tr td是改变不了的, 要被 bs的所覆盖, 要想在 style 标签中 " 覆盖" bs的默认设置的话, 须要写 完整: .table tbody tr td
  3. 总之, 选择符越详细越具体, 它的css优先级 值就越大. 优先级 就越高

css的优先级? 参考 https://blog.csdn.net/amyleeYMY/article/details/63685330

由四位数字 组成:
!important =1000,
id的优先级=100,
类, 伪类, 属性的优先级 =10,
元素, 伪元素的优先级=1
这些优先级, 无论层次, 只要有一个就 加上相应的 优先级 数值. 最后 算 总和.

可是要注意:

  1. 伪元素 只有四个, 即 :before, :after, : first-letter, :first-line , 主要是表示位置的
    伪类 有更多, 只要是表示 "状态"的, 好比 :link, :active, :visited, :hover, :focus, :first-child 等

  2. 若是有多个 相互冲突的 css规则 同时做用在同一个 元素上, 则最终 起做用的是: 以 定义这些类样式的前后顺序为准, 后定义的样式 会 覆盖 先前定义的样式, 即 后定义的样式 最终 将起做用. 而跟 该元素上 , 多个类样式 书写的前后顺序无关.

easyui的消息框 是异步的, 如何理解?

  1. 异步, 表示 它是 "非模态的", 虽然有 "遮照" 样式, 可是 它并不会阻止 该消息框 后续的代码的执行. 相反, 在执行 消息框的 回调函数时, 主函数的 剩余代码 已经执行完毕了! 因此这就是 为何主函数中 没法获取 回调函数的 返回值的缘由

  2. 那么 要想实现 模态 框的 效果, 想要 某些代码 在 点击 "肯定" 后, 再执行, 就要把 这些代码 放在 消息框的 回调函数中, 由于 回调函数 总数在 用户 单击 "肯定" 按钮后 才执行.

相关文章
相关标签/搜索