为期近两个月项目已近尾声,这里总结下学到的知识点。
-
循环里不要嵌套sql查询。
应用场景:显示课程列表页(课程名称和教师信息)
涉及表:课程表和用户表
关联字段:a_id
实例:
一次去课程表里查询10条记录
$course = M('Course')->where(array('co_id' => $id))->limit(10)->select();
显示结果
Array
(
[0] => Array
(
[co_id] => 1
[a_id] => 2
[co_title] => 数学1
[c_id] => ,2,
)
[1] => Array
(
[co_id] => 5
[a_id] => 2
[co_title] => 数学2
[c_id] => ,1,2,
)
[2] => Array
(
[co_id] => 6
[a_id] => 2
[co_title] => 数学3
[c_id] => ,1,
)
[3] => Array
(
[co_id] => 7
[a_id] => 3
[co_title] => 语文
[c_id] => ,1,3,
)
)
从结果可以看出a_id有两个不同的值2、3,这时千万不要使用循环依次查询,而应该把$course数组中的a_id提取出来再去用户表里查询相关的a_id信息,这里用getDataByArray函数,其原理就是循环$course数组,把a_id提取出来并放入一个数组中,在sql查询时使用WHERE a_id IN ($ids),最后以a_id为键重组数组
$auth = getDataByArray('Auth', $course, 'a_id');
显示结果
Array
(
[2] => Array
(
[a_id] => 2
[a_nickname] => 数学
)
[3] => Array
(
[a_id] => 3
[a_nickname] => 语文
)
)
细心的朋友就应该看到了$course数组和$auth数组如何关联了,对,在$auth数组中,键都是a_id的值,再看看$course数组,也有a_id字段,那么使用循环来处理
foreach ($course as $key => &$value) {
$value['a_nickname'] = $auth[$value['a_id']]['a_nickname'];
}
显示结果
Array
(
[1] => Array
(
[co_id] => 1
[a_id] => 2
[co_title] => 数学1
[c_id] => ,2,
[a_nickname] => 数学
)
[5] => Array
(
[co_id] => 5
[a_id] => 2
[co_title] => 数学2
[c_id] => ,1,2,
[a_nickname] => 数学
)
[6] => Array
(
[co_id] => 6
[a_id] => 2
[co_title] => 数学3
[c_id] => ,1,
[a_nickname] => 数学
)
[7] => Array
(
[co_id] => 7
[a_id] => 3
[co_title] => 语文
[c_id] => ,1,3,
[a_nickname] => 语文
)
)
2. 善用js中的indexOf方法
应用场景:课程绑定班级
实例:
如图所示,在一个显示课程的页面中,有10个课程,每个课程绑定的班级都有差异,如何在点击使用班级后弹出的框里正确高效显示已绑定的班级和让下面的班级颜色变换?注意该弹窗是在该页面里是唯一的。
下面是我的做法,先把所有班级都查询出来,再写入该页面
<div class="xin_sain">
<label class="fl">已绑定的班级:</label>
<div class="fl sa_opend bindClass">
</div>
<div class="clear"></div>
<label class="fl">未绑定的班级:</label>
<div class="fl sa_click allMyClasses">
<volist name="class.cst" id="vo">
<span rel="{$vo.c_id}">{$vo.c_title}</span>
</volist>
</div>
</div>
从上面的代码中可以看到,每个span里我都加了个rel属性,其值就是班级id,也就是说如果我在span绑定click事件,那么就可以轻易的获取班级id,而且看看第一个例子中$course数组中的c_id字段都是,1,2,这种形式的,那么在点击我的班级时,便可以使用下面代码处理了
// 获取当前点击课程
var obj = $(this).parents('.listli');
// 获取本课程已绑定的班级ID
var c_id = obj.attr('attr');
// 当前课程班级处理
var bindClass = c_id ? (',' + c_id + ',') : '';
var html = '';
$('.allMyClasses span').each(function () {
// $(this).attr('rel')前后加逗号,是为了精确匹配,如,1,2,3,中要匹配2,则是,2,
// 如果不加的话,那么,1,22,3,中用2可以匹配,22也可以匹配
var tmp = ',' + $(this).attr('rel') + ',';
if (bindClass.indexOf(tmp)!= -1) {
// 把该span节点价格xin_ds样式,表名该班级已绑定
$(this).addClass('xin_ds');
// 把匹配的班级都存储起来
html += '<span rel="' + $(this).attr('rel') + '">' + $(this).text() + '</span>';
}
})
// 最后写入到已绑定班级DOM树里
$('.bindClass').html(html);
同理,在php脚本中如果遇到类似的场景,就应该用strpos方法了。
3. 绑定点击事件,添加on样式,以便DOM操作后找到该元素
应用场景:课程绑定班级
实例:
如上图所示,有10个课程,单击其中一个课程里的使用班级弹出添加成员窗口,如何在关闭该窗口时准确高效的找到一开始点击课程的ID,代码如下
// 点击使用班级
$(document).on('click','.xin_cur',function(){
// 获取当前点击课程
var obj = $(this).parents('.listli');
// 当前课程添加on样式,其他兄弟元素去掉on样式,保持on样式的唯一性
// 以便在之后的操作中,正确找到该样式,进而找到课程ID
obj.addClass('on').siblings().removeClass('on');
// 弹出操作窗口
$('.xin_add').dialog("open");
}
4. 善用js中的slice方法
应用场景:拼凑或是获取字符串时,去掉首或尾中不需要的字符
实例:
// 去掉最后的px
var heights = parseInt($('.addtopic_box').css('height').slice(0, -2));
// 单击确定时,查找bindClass里是否有被选中的值
var c_id = '';
if ($('.bindClass').children().length > 0) {
$('.bindClass span.xin_ds').each(function () {
c_id += ',' + $(this).attr('rel') ;
})
// 去掉开头的逗号
c_id = c_id.slice(1);
}
5. 使用ajax传js数组到服务器
应用场景:活动添加页面,添加填空题,在服务器端需要php用数组接收并转换为json字符串存入数据库,存入数据库后的形式为["asdfsaf","sdfsadf"]
实例:
客户端代码
// 循环验证所有答案(填空题),把填空题的答案转为json形式
rightAnswer = [];
$('.spacelist input').each(function(i) {
if ($(this).val() == '') {
alert('请输入答案');
return false;
}
rightAnswerUrl += 'to_answer[] =' + $(this).val() + '&';
})
rightAnswerUrl = rightAnswerUrl.slice(0, -1);
$.post('__URL__/insert', rightAnswerUrl, function (json) {} 'json');
服务端代码
public function insert() {
print_r($_POST);
if (!is_array($_POST['to_answer'])) {
$_POST['to_answer'] = array($_POST['to_answer']);
}
$_POST['to_answer'] = json_encode($_POST['to_answer']);
print_r($_POST);
}
输出
Array
(
[to_answer] => Array
(
[0] => 撒旦法
[1] => 玩儿完
[2] => ewr22说2上的
)
)
Array
(
[to_answer] => ["sadf","sdafasDSF","\u6492\u65e6\u6cd5\u6492\u65e6\u6cd5\u53d1222"]
)
6. 使用parents()简化DOM操作
应用场景:群组页面中我参与的群组点击退出群组,隐藏该DOM树
实例:
DOM节点代码
<div class="group_content">
<a href="javascript:space(1)">
<img width="96" height="96" title="高端访谈" alt="高端访谈" class="fl" src="/default.jpg">
</a>
<div class="fl">
<p title="高端访谈" alt="高端访谈" class="gro_number">
<a href="javascript:space(1)">高端访谈</a>
</p>
<a href="javascript:space(1)">进入群组</a>
<p><a class="exitCrowd" cro_id="1" href="javascript:void(0)">退出群组</a></p>
</div>
</div>
如果点击退出群组时使用parent()方法,则需要一层层的往上找,而使用parents([exp])则直接祖宗元素,一步到位
// 退出群组
$(document).on('click', '.exitCrowd', function () {
if (confirm('您确定要退出群组吗?')) {
var obj = $(this).parents('.group_content');
$.post('__URL__/deleteAuth', {authId:$('input[name=a_id]').val(), croId:$(this).attr('cro_id')}, function(json) {
if (json.status == 1) {
obj.remove();
} else {
showMessage(json.info);
}
}, 'json')
}
});
7. linux服务器上开多个窗口进行转码
应用场景:后台转码,要转码的资源多,可以多开几个窗口进行转码
涉及表:资源表和我的资源表
思路:多开窗口转码,需要避免的一点是重复转码,因此需要在程序和sql字段里设置条件,sql里则是re_is_transform字段(已转码:1 未转码:0 正在转码:2),程序里则是在一进程序,则查找5个没有转码的,并立即把他们的re_is_transform变为2,再开一个窗口便不会重复转码了
实例:
function trans() {
// 查询
$transData = M($res['TableName'])->where(array('re_is_transform' => 0))->limit(0, 5)->select();
// 如果没有要转码的资源,便退出
if (!$transData) {
return;
}
// 把要转码的资源更新为2,说明此资源正在转码
$save['re_is_transform'] = 2;
M($res['TableName'])->where(array($id => array('IN', $ids))->save($save);
// 回调
trans();
}
应用场景:重新绑定页面动态生成的DOM节点事件
实例:
live语法
$('.publish').live('click', function () {
});
on语法
$(document).on('click', '.publish', function () {
})