.bind
指令
父组件将回调函数作为prop
传递到子组件是一种很常见的操作。由于OWL组件是类组件,回调函数在运行时通常需要绑定父组件的运行环境,使用.bind
指令可以方便的实现该操作。
- 类组件:类组件内部有
this
保存组件的状态,回调函数如果不绑定父组件的this
,会通过子组件的this
调用回调函数 - 函数式组件:基于函数式编程的思想,组件在两次外部输入相同的情况下,必定有一致的输出效果。函数式组件内部没有
this
指向模糊性的问题。OWL不支持函数式组件。React框架主推函数式组件。
不使用.bind
指令的写法,回调函数绑定父组件this
后,再进行传递
js
class SomeComponent extends Component {
static template = xml`
<div>
<Child callback="doSomething"/>
</div>`;
setup() {
this.doSomething = this.doSomething.bind(this);
}
doSomething() {
// ...
}
}
使用OWL提供的.bind
指令,就可以直接在模板中完成绑定,简化了代码
js
class SomeComponent extends Component {
static template = xml`
<div>
<Child callback.bind="doSomething"/>
</div>`;
doSomething() {
// ...
}
}
t-slot
指令
OWL可以定义一些通用组件,这些通用组件可以减少组件的重复定义,例如导航栏是一个通用组件,开发人员只需要根据需要向导航栏插入特定内容即可,而不需要定义一个完整的导航栏组件。在通用组件中使用t-slot
指令设置内容插入位置,使用t-set-slot
向通用组件中插入特定内容。
t-set-slot
指令的参数
有些情况下使用t-set-slot
向通用组件插入内容时,需要附加一些额外的信息,可以通过下列方式实现:
xml
<div class="info-box" t-name="InfoBox">
<div class="info-box-title">
<t t-slot="title"/>
<span class="info-box-close-button" t-on-click="close">X</span>
</div>
</div>
<!-- 使用通用组件,插入特定内容,同时传递额外信息 -->
<InfoBox>
<t t-set-slot="title" subtitle="subtitle">
Specific Title. It could be html also.
</t>
</InfoBox>
在通用组件中使用this.props.slots['title'].subtitle
就可以获取传递的参数。slot参数与props
的使用方式类似,可以使用.bind
指令对回调函数进行绑定。
t-slot-scope
指令
插入内容需要依靠通用组件内部的信息来完成渲染,此时可以使用t-slot-scope
定义一个变量,来访问通用组件内部的信息。比如下面的例子,对话框是一个通用组件,用户可以在对话框的底部插入特定内容,但是底部关闭按钮的功能依赖于对话框内部的实现
xml
<t t-name="web.Dialog" owl="1">
<footer t-if="props.footer">
<!-- 定义close -->
<t t-slot="footer" close="data.close">
<button class="btn btn-primary o-default-button" t-on-click="data.close">
<t>Ok</t>
</button>
</t>
</footer>
</t>
<Dialog>
...
<t t-set-slot="footer" t-slot-scope="dialog">
<!-- 使用变量dialog访问close -->
<button class="btn btn-secondary" t-on-click="dialog.close">
Discard
</button>
</t>
</Dialog>
当向默认插槽插入内容时,可以不使用t-set-slot
指令,此时如果需要使用t-slot-scope
指令,可以这样:
xml
<Transition visible="state.show" name="'o-fade'" t-slot-scope="transition" >
<span class="o_loading_indicator" t-att-class="transition.className">
Loading
</span>
</Transition>
插入内容的渲染context
xml
<Parent>
<Child>
<t t-set-slot="title">xxx</t>
</Child>
</Parent>
插入内容的渲染context
来自Parent组件