插值
文本
我们可以在模板中输出String
或Number
类型的数据。
<div>Hello {self.get('name')}!</div>
上述例子会建立DOM元素到组件name
属性的绑定,只要组件name
属性变更触发了update
,
DOM就会更新。
纯HTML
模板输出的数据,都会做转义来防止XSS漏洞。如果你想输出非转义html代码片段,可以将数据
赋给innerHTML
属性
<div innerHTML={self.get('content')}></div>
属性
使用{}
语法,可以动态绑定属性值,例如:
<div id={self.get('id')}></div>
// 对于取值为布尔类型的属性,会将值强制转为布尔类型
<input type="checkbox" checked={self.get('checked')} />
class属性
class属性既可以使用字符串赋值,也可以使用对象赋值。使用对象时,所有值为true
的键名
都会被当做class属性的值。
<div class="a"></div>
<div class={{a: 1, b: false, c: true}}></div> // <div class="a c"></div>
style属性
style属性可以既支持字符串,又可以支持对象赋值。用对象赋值时,需要使用属性名的驼峰命名方式。
<div style="color: red; font-size: 14px;"></div>
<div style={{color: 'red', fontSize: '14px'}}></div>
ref属性
ref属性提供了保存组件或元素引用的能力,它的取值可以是函数或者字符串。
- 如果是函数,组件或元素被挂载后,该函数会被执行。对于组件,会传入组件的实例作为参数;对于DOM元素,
会传入DOM作为参数。在组件或元素被销毁时,该函数会被再次调用,传入
null
作为参数; - 如果是字符串,则实例或者元素会绑定到
this.refs[refName]
下面。
因为
ref
是在编译时判断字符串还是函数的,所以字符串必须是字符串字面量,即:ref="name"
,如果写成表达式ref={"name"}
则会报错
<div>
// 将dom赋给组件的dom属性
<div ref={function(dom) { self.dom = dom; }}></div>
// 将实例赋给组件的instance属性
<Component ref={function(i) { self.component = i; }}></Component>
<Component ref="test"></Component>
</div>
对于循环渲染的时候(下面会讲如何循环渲染),我们可以使用对象保存引用
var Component = self.Component;
<div>
<Component
v-for={self.get('list')}
ref={function(i) {
// 使用v-for循环的key作为键名
self.components[key] = i;
}}
name={value}
ev-delete={self.delete.bind(self, key)}
></Component>
</div>
var Component = Intact.extend({
template: '<div>{self.get("name")}' +
'<button ev-click={function() {self.trigger("delete")}}>X</button>' +
'</div>'
});
var App = Intact.extend({
template: template,
defaults: function() {
return {
list: ['JavaScript', 'PHP', 'Java']
};
},
_init: function() {
this.Component = Component;
this.components = {};
},
delete: function(index) {
// 不要直接操作元数据
var list = this.get('list').slice(0);
list.splice(index, 1);
this.set('list', list);
// 如果直接操作原数据,组件不会自动更新,需要手动更新
// this.get('list').splice(index, 1);
// this.update();
}
});
window.appRef = Intact.mount(App, document.getElementById('ref'));
打开浏览器输入appRef.compoents
可以看到引用对象,当你删除一个组件后,再次输入
appRef.compoents
可以看到相应的引用也被置为null
。
删除组件或元素时,只是将引用置为
null
,你也可以判断参数是否存在,采用delete
操作来删除键名。
key属性
key属性用于给元素提供一个唯一的标识,在兄弟元素改变时,能够快速确定元素的增删改和移动。
在渲染列表时,虽然没有强制需要提供key
属性,但为列表提供key
属性是个良好的习惯。
在某些情况下,可能必须提供key
属性才能达到目的。例如进行表单操作时:
<div>
<input v-if={self.get('step') === 1} name="name"/>
<input v-else name="email" />
<button ev-click={self.toggle.bind(self)}>切换input</button>
</div>
var App = Intact.extend({
template: template,
defaults: function() {
return {step: 1}
},
toggle: function() {
this.set('step', this.get('step') === 1 ? '2' : 1);
}
});
Intact.mount(App, document.getElementById('appkey'));
可以看到,当我们往input中输入一些内容后,点击“切换input”,内容并不会删除,
这是因为底层比较两个元素时,发现是同一类元素,只是改变了元素的name
属性,
value
属性都不存在,所以没有差异,也就不会改变。这种情况也许不是我们想要的。
此时给input设置key
,则可以解决问题,因为key
不同,会删除input后重建一个
新input。
<div>
<input key="name" v-if={self.get('step') === 1} name="name"/>
<input key="email" v-else name="email" />
<button ev-click={self.toggle.bind(self)}>切换input</button>
</div>
var App = Intact.extend({
template: template,
defaults: function() {
return {step: 1}
},
toggle: function() {
this.set('step', this.get('step') === 1 ? '2' : 1);
}
});
Intact.mount(App, document.getElementById('appkeyed'));
使用JavaScript表达式
前面提到过{}
中可以书写任意合法的JS表达式。下面我们给出几个例子说明下
JS表达式就是可以作为右值的式子,简单地说:能够赋给另一个变量的式子
<div>{self.get('i') + 1}</div>
<div>{self.get('checked') ? 'checked' : 'unChecked'}</div>
<div>{self.get('message').split('').reverse().join()}</div>
<div class={self.get('className') + ' test'}></div>
// 对于复杂的逻辑,我们还可以使用自执行函数
<div>{(function() {
var ret = [];
var books = self.get('books');
for (var i = 0; i < books.length; i++) {
if (books[i].size < 100) {
ret.push(books[i].name);
}
}
// 最后返回字符串
return ret.join(' ');
})()}</div>
Vdt模板支持访问全局变量。这会使你在项目全局引入了
lodash
等工具函数库时, 可以直接在模板中方便地使用它们而无需注入模板。但灵活性是把双刃剑, 如果你在模板中过多地依赖全局变量,可能会影响到组件的复用性。