转载:http://book.odoomommy.com/chapter4/
第一章 OWL概述
OWL是什么
OWL组件是一个动态的组件树应用:
Root
/ \
A B
/ \
C D
State
state: 每个组件都能管理自己的本地状态,state是一个ES6的标准类,并无其他特殊规则。
class Counter extends Component {
static template = xml`
<button t-on-click="increment">
Click Me! [<t t-esc="state.value"/>]
</button>`;
state = { value: 0 };
increment() {
this.state.value++;
this.render();
}
}
以上代码展示了一个标准的带有本地状态的组件。需要注意的是我们需要在每次更新过组件之后手动调用render方法来渲染更新后的页面,更推荐的方法是使用useState钩子来完成组件的即时响应。
const { useState } = owl.hooks;
class Counter extends Component {
static template = xml`
<button t-on-click="increment">
Click Me! [<t t-esc="state.value"/>]
</button>`;
state = useState({ value: 0 });
increment() {
this.state.value++;
}
}
注意 t-on-click也支持行内语句:
<button t-on-click="state.value++">
Props
很多情况下子组件需要访问父组件的属性信息,实现的方式是通过在模板中添加必须要的信息,从而子组件可以通过props对象来访问必须要的信息。
需要注意的是,props中包含的信息不属于子组件,因此不能被修改。
class Child extends Component {
static template = xml`<div>Hello <t t-esc="props.name"/></div>`;
}
class Parent extends Component {
static template = xml`
<div>
<Child name="'Owl'" />
<Child name="'Framework'" />
</div>`;
static components = { Child };
}
Communication
组件间的通讯有很多种方式,其中最主要的两种方式:
- 父组件到子组件:通过props属性
- 子组件到父组件:通过触发事件
下面的代码,展示了这两种方式:
class OrderLine extends Component {
static template = xml`
<div t-on-click="add">
<div><t t-esc="props.line.name"/></div>
<div>Quantity: <t t-esc="props.line.quantity"/></div>
</div>`;
add() {
this.trigger("add-to-order", { line: props.line });
}
}
class Parent extends Component {
static template = xml`
<div t-on-add-to-order="addToOrder">
<OrderLine
t-foreach="orders"
t-as="line"
line="line" />
</div>`;
static components = { OrderLine };
orders = useState([
{ id: 1, name: "Coffee", quantity: 0 },
{ id: 2, name: "Tea", quantity: 0 },
]);
addToOrder(event) {
const line = event.detail.line;
line.quantity++;
}
}
上面的例子中,OrderLine组件触发了add-to-order的冒泡事件,事件将被父组件Parent捕获并进行数量加1的操作。 注意本例中,如果OrderLine组件中直接修改line对象也是可以的,但是并非最佳实践,之所以能够工作仅仅是因为子组件通过props接收的对象是响应式的,子组件的修耦合到了父组件中。