一个极简的JS模板库WildWood | 语法兼容vue
既生vue,何生WildWood?
Vue是一个非常先进的工具。 我非常喜欢它极简的语法,可以满足几乎所有需求。然而在实际项目中配合framework7 ui库的过程中还是踩了坑。
Vue在生成页面的时候实际上是绑定的div整个替换。这会导致问题:
- 一些dom元素上绑定的事件处理函数会被丢掉
- 一些dom元素上的一些通过js附加的自定义属性会被丢掉
所以,在使用一些依赖js的ui库时会出问题。在使用framework7 ui库的过程中就发生了一些冲突。
最终通过修改vue.js,把丢失的事件和自定义属性附加上去了,问题解决了。但是我觉得可以更简单一些,就花了2个小时写了一个更简单的库,取名叫WildWood.js.后来又花了2天时间做了一些完善. 现在已基本兼容vue的语法
Vue.min.js大小80k,比angular已经小了一些。可是.对于很多只使用一些简单模板功能的人来说,体积还是大了一些。WildWood.min.js只有3k. 总共400多行代码
WildWood在原有的dom上操作元素,与现有的js组件库可以完美共存.
so the answer is:
it is smaller, compatible, faster. So it is here.
WildWood在哪里?
去github:
https://github.com/HiYuChen/WildWood
那里有个完整的demo
先睹为快
WildWood支持的模板指令包括
{{变量}}
v-model="变量"
v-bind:value="变量"
v-bind:style="变量"
v-bind:class="变量"
v-if="变量"
v-for="for student in students"
v-on="方法()"
JS结构语法如下
var WildWood = new WildWood({
el: '#app',
data: {
/*定义变量*/
},
methods:{
/*定义方法*/
},
watch:{
/*定义监听变量的函数*/
},
computed:{
/*定义根据一些变量自动计算数值的函数*/
}
};
使用上的几个限制:
- 嵌套for in block中变量的使用
假设
data:{
total:300,
arrStudents:[
{name:'tom',
subjects:[{name:'chinese'},[name:'english'}]
},
{value:13},
subjects:[{name:'chinese'},[name:'english'}],
],
}
在嵌套的for row in arrRows 这样块里可以使用当前块的变量或者全局变量,但是不能引用外层for 块里的变量, 如下所示
<li v-for="student in arrStudents" >
<ul>
<li v-for="subject in student.subjects" >
<div>{{subject.name}} </div><!--OK-->
<div>{{total}} </div><!--OK-->
<div>{{student .name}} </div> <!-- 不允许 -->
</li>
</ul>
</li>
- 数组中对象属性的监听原则
array中的对象中的属性要在放进数组之前就定义好.不能后来再修改。array中的对象中的属性要在放进数组之前就有.不能后来再修改。否则就无法监听到该属性的变化了。
比如:
arrStudents中student一开始没有score属性,在添加到arrStudents后,执行
arrStudents[0].name=‘jack’; 这就是错误的用法。
正确的方式应该是:
var student={name:‘jack’,score:‘90’};
arrStudent.push(student);
这是因为在push的时候,wildWood就开始监听student的属性变化了。后加的属性就监听不到了。
来一个实际的例子
HTML:
<div>
<div style="display:flex;">
<div>Total:</div>
<div >
<input type="text" v-model="totalAmount" placeholder="Please input" >
</div>
</div>
<div style="display:flex;">
<div>Coupon:</div>
<div >
<label>{{couponAmount}} </label>
</div>
</div>
<div style="display:flex;">
<div>Coupon:</div>
<div >
<label>{{cashAmount}} </label>
</div>
</div>
</div>
<div style="margin-top:10px;margin-left:10px;">Please select a coupon</div>
<div>Selected coupon id is: {{m_couponToUse}}</div>
<div>
<ul>
<li v-for="row in m_coupons" >
<div style="display:flex">
<input type="radio" name="radio_coupon" style="" v-on:change ="couponClicked();" v-bind:value="row.coupon_id" v-model="m_couponToUse" />
<img v-bind:style="{visibility:row.isChecked?'visible':'hidden'}" style="width:32px;height:32px;" src="check.svg"/>
<div>
{{row.value}}元
</div>
<div></div>
<div class="item-title">{{row.goods_name}}</div>
</div>
</li>
</ul>
</div>
JS代码:
var WildWood = new WildWood({
el: '#app',
data: {
couponToUse: '',
couponAmount: 0,
totalAmount: '',
cashAmount: 0,
m_coupons:[ { isChecked: false, coupon_id: '3', goods_name: 'cup', value: '30' },
{ isChecked: false, coupon_id: '4', goods_name: 'book', value: '40' }
],
oper:'jack'
},
methods: {
couponClicked: function () {
var i;
for (i in this.m_rows) {
var r = me.m_rows[i];
if (r.coupon_id === me.m_couponToUse) {
me.m_couponAmount = r.value;
r.isChecked = true;
}
else r.isChecked = false;
}
},
},
watch: {
couponAmount: function () {
if (parseFloat(this.couponAmount) > 0 && (this.totalAmount === '' || this.m_totalAmount < this.m_couponAmount)) {
this.m_totalAmount = this.m_couponAmount;
}
},
},
computed: {
cashAmount: function () {
return this.totalAmount - this.couponAmount;
}
}
});
完整demo请到github下载:https://github.com/HiYuChen/WildWood