都变了样!我这样用jCT模板.

本文介绍了一种名为jCT的模板技术,通过独特的重构语法打破了传统平面化和顺序化的限制,实现了自由布局,并通过thisCallback机制实现了灵活的数据装配流程。

在写这篇文章的时候我相信很多朋友都不明白我在说什么,会奇怪我这样的思路,问题就在这里,我的这种思路很难被认同.但是这种思路开发起来真的很快.请耐心看完所有的文章.

 

jCT发展到目前的第三版.除了jCT本身的变化外.我在使用的时候整个设计思路也都改变了.

对于模板技术来说,绝大多数是平面化,顺序化.也就是说

1.模板的结构和页面表现的结构一致--------------------平面化

2.模板成为视图的时候数据的装配是顺序进行的--------顺序化 (这个说法看了我下面的实现就会明白)

 

下面是我准备重新写的nicEditor打包工具模板部分.(注意<!---xxx-->是jCT的模板语法,<!--xx-->是我写的注释)

<!--1:下面一段用来确定页面的布局-->
<div id="" class=""><center class="fsh2 cwhite">选择 NicEdit 模块</center></div>
<div id="" class="">
	<span>合并GIF图标文件:</span>
	<input type='text' name="iconsfile" value="nicEditIcons.gif"/>
</div>
<div id="navmenu" class="" />
<div id="nelist" class="">nE List</div>
<!--这里用jCT重构语法,确定了执行的过程-->
<!---
	/*+Main*/
function(D){
	...//这一句将被jCT生成的实例主体过程替换
	$('#mainbody').html(this.CTV.join(""));//把结果也就是上面的布局写入到#mainbody Element
	$('#mainbody .abc').abc();//这是我写的一个jQuery插件 Action By Class name,可以忽视它
	this.navmenu('#navmenu');//调用导航菜单
	this.nelist();//调用从服务器取得的nicEditor的模块列表
}
-->
<!--1:布局结束-->
<!--jCT的Run语法,Run里的代码只运行一次.这里的例子相当于动态的定义了一个函数-->
<!---/*+Run*/
$.extend(App,{
test:function(){
	alert($('img').attr('value'));
	return false;
}
});
-->
<!--2:导航菜单部分, abc abc.lavaLamp(...) 是jQuery插件 Action By Class name 的执行方法-->
<!---/*+Child navmenu*/-->
<ul class="lavaLampBottomStyle bgc4 cwhite fwbold fsh4 abc abc.lavaLamp({fx:'easeOutBack',speed:700})">
	<li class="inline"><a onclick="return App.test();">测试</a></li>
	<li class="inline"><a onclick="return App.test();">下载</a></li>
</ul>
<!--道理同前面的重构-->
<!---/*+Main*/
function(){
	...
	var el=arguments[0];
	if (!el) return this.CTV.join("");
	$(el).html(this.CTV.join("")).find('.abc').abc();
}
-->
<!---/*-Child navmenu*/-->
<!--2:导航菜单部分结束-->

<!--3:nicEditor的模块列表-->
<!---/*+Child nelist*/-->
<table class="dlTable" cellpadding="0" cellspacing="0">
	<tbody>
		<!---for(var I=0;I<nelist.length;I++){-->
		<tr class="core">
			<td>
				<img style="width:30px;height:30px;" class="checkbox" src="+-App.pixelGif-+" name="plugins[]" value="+-nelist[I]-+" />
				<input name="plugins[]" value="+-nelist[I]-+" type='checkbox' class="none" />
			</td>
			<td class="pluginName">+-nelist[I]-+</td>
		</tr>
		<!---}-->
	</tbody>
</table>
<!--道理同前面的重构,不过里面用到了一个thisCallback,后面叙述-->
<!---/*+Main*/
function(D){
	if(arguments.callee.caller!=thisCallback)
		return jsonQueue({nelist:0},this);
	with(D){...}
	$('#nelist').html(this.CTV.join(""));
	$('#nelist table img').each(function(){
		$(this).click(function(){
			var ck=!$(this).next('input').attr('checked');
			if (ck){
				$(this).next('input').attr('checked','checked');
				$(this).addClass('checkboxon');
			}else{
				$(this).next('input').removeAttr('checked');
				$(this).removeClass('checkboxon');
			}
		}).click();
	});
}
-->
<!---/*-Child nelist*/-->
<!--3:nicEditor的模块列表结束-->

 

可以看到,传统的平面化 在我这个例子了已经不复存在了.jCT重构语法为自由布局提供了可能.

顺序化 thisCallback (这个名词我还是不满意)彻底打破.

 

关于 thisCallback 到底是什么东西请看:

http://achun.iteye.com/blog/209575

http://achun.iteye.com/blog/210023

jsonQueue就是这种想法的一个实例:

//回调函数,保持原来的this指针
function thisCallback(func,thiss,args){
	func.apply(thiss,args);
}
//jsonQuene合并细粒度队列回调
function jsonQueue(queue,thiss,ask){
	if (ask){
		var ask='确定执行这个操作么?'+(options.ask===true?'':options.ask);
		if(false==confirm(ask)) return false;
	}
	var func=arguments.callee.caller;

	var data=JSON.stringify(queue);
	(function (func,data){
	jQuery.ajax({
		url: R('/'),
		dataType:'json',
		data:data,
		type:'POST',
		error:function(xml){
			alert('Error : actionQuene');
		},
		success:function(a){
			thisCallback(func,thiss,[a]);
		}
	});
	})(func,data);
	return false;
}

其他信息参见

降低前后台业务逻辑上的耦合度,前后台细粒度数据通讯的方法

当然我这种用法有些极端(不必要),但怎么说呢.对于这个例子完全可以把3部分写到一起.不过我喜欢的开发形式.jCT和thisCallback为这种提供了可能.

 

非常好的问题! 我们来详细分析你提供的这段代码: ```cpp const JunctionInfoCity* candidate = nullptr; for (const auto& jct : junctions_info_city_) { if (jct.offset > 0 && jct.offset < 300) { if (!candidate || jct.offset < candidate->offset) { candidate = &jct; } } } if (candidate) { const auto& junction = *candidate; // ... 后续条件判断 ... } ``` --- ### ✅ 答案:**不需要 `break`** #### 🔍 原因解释: 这个 `for` 循环的目的是: > **在所有 `0 < offset < 300` 的路口中,找到 `offset` 最小的那个(即最近的一个前方路口)** 这是一个 **“找最小值”** 类型的遍历,必须访问完所有符合条件的元素才能确定哪个是最近的。因此: - ❌ 不能在找到某个候选时就 `break` - ✅ 必须让循环完整运行到最后,确保没有更近的路口被遗漏 举个例子: 假设容器中有以下 `offset` 的路口:`[50, 20, 80, 10]` 即使你在前几次迭代中先看到 `50`、然后是 `20`,你也必须继续看下去,直到确认 `10` 是最小的。 所以: > ✅ **这个循环不仅不该加 `break`,反而要保证它走完全部元素。** --- ### 📌 对比:两种不同逻辑策略 | 策略 | 是否需要 `break` / `return` | 说明 | |------|-------------------------------|------| | **策略一:遇到第一个满足条件的就返回**<br>(如原始逻辑) | ✅ 需要 `break` 或 `return` | 贪心式处理,提高效率 | | **策略二:先找 offset 最小的路口,再判断条件** | ❌ 不需要 `break` | 必须遍历完才能确定“最近” | 你现在问的正是 **策略二**,它的优势是:**不会因为容器顺序混乱而误判“最近路口”**。 --- ### ✅ 完整示例:带条件判断的版本 下面是完整的、正确的写法(无需 `break`): ```cpp bool SdNavigationCity::IsApproachMergeJCT(JunctionInfoCity &merge_jct) { // 第一步:找出 offset > 0 且最小的那个路口(最近前方路口) const JunctionInfoCity* candidate = nullptr; for (const auto& jct : junctions_info_city_) { if (jct.offset > 0.0 && jct.offset < 300.0) { if (!candidate || jct.offset < candidate->offset) { candidate = &jct; // 更新为更近的路口 } } } // 如果没找到任何前方路口 if (!candidate) { SD_COARSE_MATCH_LOG << "[IsApproachMergeJCT] No valid junction with positive offset found."; return false; } const auto& junction = *candidate; // 第二步:检查这个“最近路口”是否为合流口且满足条件 if (junction.junction_type_city == JunctionTypeCity::RoadMerge && junction.junction_state_city != JunctionStateCity::PASSED) { if (junction.prev_road_class.size() == 2 && junction.road_merge_main_road_lane_nums == junction.target_road_lane_nums) { bool is_main_on_correct_side = false; if (junction.split_merge_direction == DirectionSplitMerge::Left) { is_main_on_correct_side = (junction.prev_road_class.front() == RoadMainType::RoadMain); } else if (junction.split_merge_direction == DirectionSplitMerge::Right) { is_main_on_correct_side = (junction.prev_road_class.back() == RoadMainType::RoadMain); } if (is_main_on_correct_side) { merge_jct = junction; SD_COARSE_MATCH_LOG << "[IsApproachMergeJCT] APPROACHING MERGE JUNCTION (nearest): offset=" << junction.offset; return true; } } } SD_COARSE_MATCH_LOG << "[IsApproachMergeJCT] Nearest junction does not meet merge criteria."; return false; } ``` --- ### ✅ 总结 | 问题 | 回答 | |------|------| | **这个循环需要加 `break` 吗?** | ❌ 不需要!必须遍历完所有元素才能确保找到 `offset` 最小的路口。 | | **什么时候可以加 `break`?** | 只有当你明确“不需要后续数据”时,比如已找到目标且不关心其他项。 | | **这种做法的好处是什么?** | 更鲁棒:即使 `junctions_info_city_` 未按 `offset` 排序,也能正确找到最近路口。 | --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值