下载地址是: www.jeasyui.com/download
当前版本是1.6.7 是由 jquery ui 扩展而来的.
像jquery ui, bootstrap, jquery easyui三者都是类似的ui框架, 感觉 easyui如其名一样, 是最简单最宜用的, 而且包含的 前端组件是最全面的. 当jquery ui和easyui的 tabs dialog等组件名称有 冲突(相同时), 可以
定制jQuery组件,只保留jQueryUI中的Tabs, Dialog. (其他的如DatatimePicker等使用EasyUI重写);这样我们会得到一个只有40K的jQueryUI文件. 然后 将精简后的jQueryUI加载到EasyUI引用之后,这样EasyUI的Tabs和Dialog就会被复写。
easyui 比jquey ui 要"重一些", 所以 jquery ui适合前台,easyui适合后台,但我想何必添加2个库呢,直接一个easyui不就行了,反正也不大多少.
如何选择 bootstrap和 easyui?
bootstrap侧重于css, 侧重于前端, 样式很美观精美, 但是js/组件功能不是很全面充足, 而easyui则 侧重于 后台, 有很多强大的js, 所以做后台一般用easyui.
所谓的web开发有很多ui框架, 但是就这样定了, 前端用bootstrap的css, 后台用 easyui的各种组件, 或用easyui的 bootstrap主题
- local和 locale的区别: 前者是一个形容词, 标识"局部的, 当地的", 后者 是一个 名词, ['l2u'k2l] 表示 "地点, 地方, 场所"等.
- 在 easyui的 语言包中是 : locale/ 文件夹.
====================================
js中有两个函数,以前很混淆, 其实还是很简单的:
setTimeout是只执行一次, 而setInterval是重复多次周期性的执行回调函数。 两个函数的时间都是以 毫秒为单位, 比如 1000, 2000表示1秒, 2秒
setInterval 会返回一个 定时器的句柄handle, 这个句柄就是 用来关闭定时器的, 用 clearInterval
Interval是 inter + val (inter value) 间隔值的意思easyui有很多组件可以方便的和后台php之间进行数据交换, 获取后台的数据装载到组件中, 主要是通过 "href或url"属性来实现的. 而且是ajax方式, 还有loading效果, 这一点很重要也很方便, 虽然都写得来,但是没必要自己去写, 可以更专注于业务代码的书写.
php中 , (包括所有的语言中), 都要善于使用 "等待/ 延时, 延迟"的语句, 并不是 所有的代码都必须要一开始就执行, 有的时候, 需要 "等一下" 再执行! 一定要有这样的意识! php中用 sleep($second秒数)函数 来等待由于eu=easyui 在构造 组件的时候, 不需要自己去写大量的 html, 所以 非常简洁和方便(相比 bootstrap那样要记忆大量的类名而言)
在eu, bs等框架中, 所谓的 "折叠" 面板, 折叠就是 面板上有一个 按钮, 通过这个按钮, 可以显示和隐藏 面板的 内容部分: 这个是通过 css的 属性 : display: none 来实现的. (display的属性很多, 有 block, inline等等, 也有none 这个属性, 表示不显示)
div和p元素的自动增高? 和最小高度?
div和p本身就是 自动增高的, 不需要设置.
只是当div和p中 的内容很少的时候, 他的高度会塌陷, 你可以设置固定的 尺寸, 也可以设置一个 最小高度, 这样 即使内容很少, 也能保证 不塌陷.
最小高度 也是一个标准的css属性: 浏览器都支持, 比如:div { min-height: 200px; }
=================================
json格式本身就是 用大括号括起来的 键值对 的字符串, 一个 json至少 必须是 用 { }括起来的, 或者是 多个 { }组成的数组, 所以, 对json 变量是可以用 (js中 的 + 号运算) 和 php中的 点号 连接运算。
比如: $json = ''; while(...) {... ; $json .= $row; } echo $json;
打印数组的效果,由于浏览器 会 忽略源代码中的 回车键enter, 使得数组的输出挤在同一行, 这时可以配合 “查看页面源代码 ” 来查看, 在源代码中就会显示得 比较 "可读". 更加清晰。
比如print_r($json 数组)
-> "查看页面源代码"在大多数框架中,当元素支持ajax 后台数据获取和交换的时候, 使用 url和 href属性的时候, 是从后台获取数据的。 为了能够看到、模拟出 在实际远程、慢速http网络中的 等待载入loading... 的效果,通常可以在后台php文件中, 用
sleep(waitSecond);
来写。 要灵活的, 善于使用 sleep函数 。php的后台 文件 、不是函数, 用来向 前台页面提供 ajax返回数据的时候, 不是用的 return语句(return语句是 函数返回时用的), 而是用的 echo语句输出: 非输出语句 对前台是没有影响的, 只有echo语句的结果才有效
字符串截取函数不再疑惑: 在php中 用substr(start, len),索引从0开始; 在mysql中 用substring , 索引 从1 开始; 而在JavaScript中 用substr和substring 两个函数, 前者是 substr(start, len),后者是 substring(start, end);
重要的是, php中 如果要表示 "只取字符前面多少个字符= =去掉字符串最后面几个字符" 此时使用
substr($json, 0, len)
,但是也可以使用substr($json, 0, -1/- 去掉最后的结尾字符的个数, 比如 -2, -3等等) 去掉字符串最后的一个字符
会更简洁。 比substr($json, 0 , $len-1)
更简洁而且不必知道字符串的长度了。
- 通常 什么叫异步的? 就是 回调函数 就是 异步的!
======================================
通常情况下, eu中的组件 , “方法”调用的方式是 $ ('#节点'). 组件名('方法名', [参数])
但是 消息框组件messager 比较特殊, 他的方法调用不依赖于dom中的节点, 直接用 $ 来调用。 而且方法调用 是普通的 函数名加 参数的方式,比如: 警告框的调用是: $. messager. alert('标题名', '警告内容', '图标的名称error, warning, info, question' , function(){..回调函数 }
其他消息框的 回调函数, 有一个 r 参数, r表示的是 response 回应, 即你按的是 哪个 “ok” 还是 “cancel” 按钮, 所以 有 if(r) {...}
分页的原理是:页面的pagination 实际上是一个 div, 显示的内容 你是可以自定义的。 根据 预先设置的pageSize, pageList 和 当前你选定的页面序号 pageNumber, 来决定当前页要显示的内容。 关键是每页显示的内容 是从后台url.php页面ajax过来的, url.php要传递回来的数据包括两个, 一个是 记录的总条数totals, 这样来决定分多少页; 另一个是rows: [{...}, {....}, {...}] 的json数组,来决定每一次返回的是哪些不同的记录数据。 因此, 在url.php中, 就是根据从前端传递过去的这些 pageSize, pageList 和 当前你选定的页面序号 pageNumber 参数, (这些参数 默认的是 通过 post方法 传递到后台的), 你可以在 firebug中 看到 前台页面传递到 后台的 参数, 你就 在 url.php的后台页面中 去 $_POST['参数']
获取到这些参数, 然后 使用 thinkphp的 find 方法, select方法等去 limit () 链式操作去 获取数据库中的 记录 ,然后 把这些记录 赋值给 rows 变量. 那么这个 rows就会 返回到 前台页面显示出来了.
关于 easyui的一些知识点
eu中的组件 在 进行一些操作(主要 是 显示/隐藏 操作) 后, 可能会造成 位置的 错位, 为了恢复到 原来的位置 状态, 可以调用 它的 resize 方法, 比如 :
$('acc').accordion('resize');
eu中的通用的思想, 可以设置通用的 "默认设置 / 属性" :
$.fn.resizable.disabled = true;
通用的默认方法有: disable, enable, options , 注意这个是没有 ed的
通用的事件有: onStart, onStop等...
属性 是 disabled , 带ed的, 表示 状态, 方法是 动词, 比如 enable, 是 表示 去做什么, 而事件 是表示 当 什么的时候 去做什么 动作, 所以 也是 : on + 动词, 比如: onSelect等
eu的方法, 都是 在 对应 的 组件名称 后 ( '方法名', [参数]), 比如:$('prog'). progressbar('setValue', 60);
eu中的 宽度和 高度等 表示 数值的 , 使用的格式 都是 纯数字的, 不需要在后面 加px了, 比如: width: 500
eu中的组件,比 bs的使用方法 要 简单 得多, 基本上 你不需要 去记忆那么多复杂的 class, 你只需要写html结构就好了, 而且 绝大多数 都是使用的 div 结构, 只有 少数的几个 组件使用 是 a 标签 比如 linkbutton 组件等.
注意, accordion 组件的 单词写法, 两个 字母 都是 o, 最后一个不是 字母a.
- 注意 pagination 组件的传参, 是在firebug中查看 到底是传了哪个 参数、什么参数, 这样才好在url.php服务器端获取这个参数
panel和window等组件, 从外形上来说, 都差不多, 都有标题栏和客户区, 主要还是一个 语义上的差别: 它们 默认 提供的方法和事件 不同. 你也可以把 panel通过定义 一些自定义的属性,改造成 window, 但是这样做就不合适.
如果你从 语义上 来说, 就是需要的 一个 window, 那么你就是用window 组件, 而不要是用 panel, 如果你并不需要 窗口的事件和方法, 那么你就只使用 panel就好了.
panel组件是很多组件的基础, 都依赖于它, 如tabs, accordion(分类组件), 这些组件实际上是 多个panel 的组合.
因此, 这些组件就会有两种属性和方法, 一个是 组件自身的 独有的方法和属性; 另一个是从 panel继承来的属性.
ajax从后台获取的交换数据文件, 可以是任意的文件,不一定 必须是 php文件, 任何的 txt, html, asp,jsp文件都是可以的, 只要是有 "输出" 内容的 都可以!
tabs组件 在eu中是 很简单的,其索引是从 0 开始, 而且 并不是必须要有一个选项卡被选中的, 可以都不被选中的.
关于 onbefore和 onAfter事件?
凡是onBefore... 的都可以在 事件的函数 代码中, 根据不同的 情况返回 false, 那么对应的 ... 事件 将不会被执行;而 on... 的事件 通常是 指 相应的事件/动作 完成之后 执行的, 而不是指 事件正在执行的同时 去执行 on...函数体, 因为js 不可能 在 事件正在执行的时候, 去执行js代码,所以onload是指全部的 document文档都被加载完成后, 才去执行的代码,而不可能是 一边加载文档dom , 一边去执行js代码的。 跟 onAfter...作用是一样的, 而通常很多组件都没有提供 onAfter...事件
- 所有的浏览器页面内容, 都是window对象, window对象是一个最大的 基类对象。window对象 有很多属性和方法,比如history, 比如 location, 比如document等, 而且,这些属性 本身也是一个对象,本身也有一些属性和方法, 比如
location.href , 比如document.click(function(){...});
所以 要注意 区分 window和 document的 关系, 不要把它们搞混了。
通常 在 调用 window的方法 和属性时, 可以省略这个 window对象。 比如:window.alert(...) 就写 alert(....)
=========================================
区别 方法和 方法选项?
onStartDrag等事件, 是作为 { 属性中的选项} 来使用的, 放在 初始化方法 Draggable里面的,
而方法 比如 Disable等 则是 放在 初始化 方法 外面的, 跟初始化 方法 是 并立 平齐的.
要修改 kindeditor的 背景, 需要在css文件中的 项目 : .ke-container 和 .ke-edit-textarea 中 进行修改
如何设置 kindeditor 的 文本框区域 自动 随内容 增高?
在create方法的选项中:
afterCreate: function(){
this.loadPlugin('autoheight');
},
myeditor. edit.setHeight(500); /////// 注意: kindeditor 的 myeditor是 整个editor组件对象, 其中的 可编辑区 是myeditor的一个属性: edit, 它也是一个对象, 有相关的方法...
或者:
editor.edit.setHeight("600");
var autoheight = editor .edit.doc.body. scrollHeight;
editor.edit.setHeight(autoheight);
php的类的const?
const 常量 是属于 类, 而不是属于 某个具体的对象的, 所以 要用 类名 来引用 比如: const INSERT_MODE=1; 引用时 className::INSERT_MODE
通常使用的场合是: 如果只是在类的内部, 要定义几种并列的情形, 有几种选择, 想用数字来区分, 但是为了便于 记忆和 表义, 就可以使用 类的 常量来做.
如果要在 全局都使用 的常量, 就使用 全局 常量, 使用 define来定义
tp的命名范围: 定义一个变量 $_scope 注意不是 命名空间, 实际的目的, 是将前面 的多个连贯操作换了一个方式, 将多个连贯操作封装 /集合到一起了的意思.
对tp 的查询结果 也可以 强制 使用索引, 即使用 index连贯操作. 方法是:
$user->index('user') -> select();
要注意 这个索引 字段 必须是 实实在在的/ 已经在 数据库的数据表上 创建了 对应的 字段 'user' 的 索引了.
token是表单提交时 用来 防止 重复 /多次 提交表单的 连贯 操作, 一般 放在 create方法之前: $user->token(false/true是否采用 令牌随机数验证) -> create();
token的原理?
token就是 令牌, 实际上就是 session 中的一个随机数, 随机id.其最大特点是随机性, 不可预测, 一般黑客或软件无法猜测出来.
token主要用于两个地方: 放在表单 重复提交; 防止 anti csrf攻击(cross server/site request fault 跨站点请求伪造)
两者在原理上都是通过 session token 来实现的, 当客户端请求页面时, 服务器会生成一个随机数token, 并且将token放到服务器上session当中, 然后将token放在发给用户的数据文件中,( 一般是用 hidden隐藏表单的方式), 下次客户端提交请求时, toke 会随表单一起提交到服务器.
当用于 anti-csrf攻击, 服务器端会对 token值进行验证, 判断请求中 的token和 服务器上保持的 token值是否相等...
如果用于 防止表单重复提交, 则在服务器端第一次验证相同过后, 会将 session中的token值更新一次, 所以 当用户重复提交时, 后面的验证就会失败, 因为用户提交的表单中的token没变, 但服务器端session中的token已经改变了.
strict连贯操作 "是否严格检查", 是 tp的3.2.3 新增的, 主要是 用于 设置 在 新增/更新(add操作和 save)记录时, 判断 数据源中的字段 是否 跟数据表中的 字段 (个数和类型 )是否 完全一致, 如果 不一致, 在strict(false)时, 会忽略 数据表中没有 而数据源中 有的字段, 如果strict(true)时, 则会 抛出异常.
$user -> strict(true) -> add($data);
作为tp框架, 的开发者,肯定是要完善和提供 各种各样的 features和 functionalities, 但是作为 使用者, 其实是没有必要 把它的各个方面 完完全全的掌握的, 只要掌握 最主要的//大约 60% 的东西 和 内容 就可以了, 如同我们在使用 office等任何其他软件一样.
====================================
从多个表中取得数据, 可以有三种方法/方式, 牵涉到 三个方面的东西: 联合操作join查询; 视图模型; 关联/关系(relation)模型. 三个方面究竟哪个更好更科学呢?
tp的数据库操作
- delete方法返回值, 是成功删除的记录数; 如果返回值是false, 表示sql查询语句出错; 如果返回0 表示没有删除任何数据(即: 没有符号条件的记录)
- 对数据库的所有操作, 都应该限制条件或 个数?? 通常 用 order和limit 来限制.
关联模型
关联模型中 有两个表, 当前模型类所对应的表, 或者说,mysql当前正在操作的/执行的表, 叫 主表, 参照表, 那么另一个表(被关联的/被躺枪的表)叫 关联表.
关联表的关联 通常用 mapping 来表示
- 只有当前 操作的表 即 参照表 所对应的 模型类 才需要创建, 其他 被关联表 的模型都不需要创建, 会自动定位到对应的关联表.
- 即使定义了关联模型类, 也可以只是对当前表 (就它一个表) 进行curd操作, 只要你不写 relation 连贯操作方法.
- relation(的参数, true表示获取所有被关联的数据, 也可以只获取某一个关联模型的数据), 也可以先获取 参照表 数据, 然后用 relationGet去获取关联数据
- 关联操作, 只是在普通操作(单表操作)的基础上 加一个relation()的连贯操作而已, 主体操作还是 find, select, add, save等
==================================================
唯一数据记录查询?
查询唯一数据的时候, 是 使用distinct 关键字, 这个distinct相当于一个 形容词, 修饰语, 用来 修饰 要查询的字段 , 是 唯一的, 不能重复. 如果 使用 "distinct * " 而又有 id 主键的话, 将不能 过滤唯一性字段的值 , 因为有主键id本身就是 唯一的了.
**要注意的是, distinct 是 根据 distinct 后面所有字段 合起来时 的数据 一起 来判断 是否是相同的. 而不是 紧挨着 distinct关键字的那个字段. 比如: distinct name, 则只会看name字段 是否相同的唯一性, 如果 是 distinct name, age 则会 判断 只有当 name和age两个 字段的 值 都相同时 , 才认为是 相同记录, 被 过滤掉, 如果 只是 name相同, 而age不同, 则认为是两条 不同的记录, 不会被 distinct 所过滤. **
避免在最高层使用 distinct 应该是一条基本规则 。原因在于,即使我们遗漏了连接的某个条件, distinct 也会使查询 " 看似正确 " 地执行 —— 无可否认,发现重复数据容易,发现数据不准确很难,所以避免在最高层使用 distinct 应该是一条基本规则。 发现结果不正确更难.....
mysql> select * from user;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 1 | zhangsan | 20 |
| 2 | lisi | 30 |
| 3 | jack | 20 |
| 4 | mike | 20 |
| 5 | jack | 10 |
| 6 | ??? | 10 |
| 7 | jack | 10 |
+----+----------+------+
7 rows in set (0.00 sec)
mysql> select distinct name, age from user;
+----------+------+
| name | age |
+----------+------+
| zhangsan | 20 |
| lisi | 30 |
| jack | 20 | // 这里的 两个 jack age 会认为是不同的记录
| mike | 20 |
| jack | 10 |
| ??? | 10 |
+----------+------+
6 rows in set (0.00 sec)
mysql> select distinct name from user;
+----------+
| name |
+----------+
| zhangsan |
| lisi |
| jack | // 这里的两个 jack 被 distinct所过滤
| mike |
| ??? |
+----------+
5 rows in set (0.00 sec)
mysql>