mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
+105
-20
@@ -9,6 +9,7 @@
|
|||||||
- [Properties](#properties)
|
- [Properties](#properties)
|
||||||
- [Methods](#methods)
|
- [Methods](#methods)
|
||||||
- [Lifecycle](#lifecycle)
|
- [Lifecycle](#lifecycle)
|
||||||
|
- [Semantics](#semantics)
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@@ -67,9 +68,9 @@ change to it will cause a rerendering.
|
|||||||
|
|
||||||
## Composition
|
## Composition
|
||||||
|
|
||||||
The example above shows a QWeb template with a `t-on-click` directive. Widget
|
The example above shows a QWeb template with a `t-on-click` directive. Widget
|
||||||
templates are standard [QWeb](qweb.md) templates, but with an extra directive:
|
templates are standard [QWeb](qweb.md) templates, but with an extra directive:
|
||||||
`t-widget`. With the `t-widget` directive, widget templates can declare sub
|
`t-widget`. With the `t-widget` directive, widget templates can declare sub
|
||||||
widgets:
|
widgets:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
@@ -91,7 +92,7 @@ In this example, the `ParentWidget`'s template creates a widget `MyWidget` just
|
|||||||
after the span. See the [QWeb](qweb.md) documentation for more information on the
|
after the span. See the [QWeb](qweb.md) documentation for more information on the
|
||||||
`t-widget` directive.
|
`t-widget` directive.
|
||||||
|
|
||||||
Note that the rendering context for the template is the widget itself. This means
|
Note that the rendering context for the template is the widget itself. This means
|
||||||
that the template can access `state`, `props`, `env`, or any methods defined in the widget.
|
that the template can access `state`, `props`, `env`, or any methods defined in the widget.
|
||||||
|
|
||||||
**CSS and style:** there is some specific support to allow the parent to declare
|
**CSS and style:** there is some specific support to allow the parent to declare
|
||||||
@@ -106,17 +107,15 @@ root widget element.
|
|||||||
|
|
||||||
Warning: there is a small caveat with dynamic class attributes: since Owl needs
|
Warning: there is a small caveat with dynamic class attributes: since Owl needs
|
||||||
to be able to add/remove proper classes whenever necessary, it needs to be aware
|
to be able to add/remove proper classes whenever necessary, it needs to be aware
|
||||||
of the possible classes. Otherwise, it will not be able to make the difference
|
of the possible classes. Otherwise, it will not be able to make the difference
|
||||||
between a valid css class added by the component, or some custom code, and a
|
between a valid css class added by the component, or some custom code, and a
|
||||||
class that need to be removed. This is why we only support the explicit syntax
|
class that need to be removed. This is why we only support the explicit syntax
|
||||||
with a class object:
|
with a class object:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
<t t-widget="MyWidget" t-att-class="{a: state.flagA, b: state.flagB}"/>
|
<t t-widget="MyWidget" t-att-class="{a: state.flagA, b: state.flagB}" />
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
An Owl component is a small class which represent a widget or some UI element.
|
An Owl component is a small class which represent a widget or some UI element.
|
||||||
@@ -196,15 +195,15 @@ A solid and robust component system needs useful hooks/methods to help
|
|||||||
developers write components. Here is a complete description of the lifecycle of
|
developers write components. Here is a complete description of the lifecycle of
|
||||||
a owl component:
|
a owl component:
|
||||||
|
|
||||||
| Method | Description |
|
| Method | Description |
|
||||||
| ------------------------------------------------ | --------------------------------------- |
|
| ------------------------------------------------ | ----------------------------------------------------- |
|
||||||
| **[constructor](#constructor)** | constructor |
|
| **[constructor](#constructor)** | constructor |
|
||||||
| **[willStart](#willStart)** | async, before first rendering |
|
| **[willStart](#willStart)** | async, before first rendering |
|
||||||
| **[mounted](#mounted)** | just after component is rendered and added to the DOM |
|
| **[mounted](#mounted)** | just after component is rendered and added to the DOM |
|
||||||
| **[willUpdateProps](#willupdatepropsnextprops)** | async, before props update |
|
| **[willUpdateProps](#willupdatepropsnextprops)** | async, before props update |
|
||||||
| **[willPatch](#willpatch)** | just before the DOM is patched |
|
| **[willPatch](#willpatch)** | just before the DOM is patched |
|
||||||
| **[patched](#patchedsnapshot)** | just after the DOM is patched |
|
| **[patched](#patchedsnapshot)** | just after the DOM is patched |
|
||||||
| **[willUnmount](#willUnmount)** | just before removing component from DOM |
|
| **[willUnmount](#willUnmount)** | just before removing component from DOM |
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
@@ -212,7 +211,7 @@ Notes:
|
|||||||
then on children, and `[Xed]` are called in the reverse order: first children,
|
then on children, and `[Xed]` are called in the reverse order: first children,
|
||||||
then parent.
|
then parent.
|
||||||
- no hook method should ever be called manually. They are supposed to be
|
- no hook method should ever be called manually. They are supposed to be
|
||||||
called by the owl framework whenever it is required.
|
called by the owl framework whenever it is required.
|
||||||
|
|
||||||
#### `constructor(parent, props)`
|
#### `constructor(parent, props)`
|
||||||
|
|
||||||
@@ -307,7 +306,7 @@ scrollbar.
|
|||||||
|
|
||||||
Note that modifying the state object is not allowed here. This method is called just
|
Note that modifying the state object is not allowed here. This method is called just
|
||||||
before an actual DOM patch, and is only intended to be used to save some local
|
before an actual DOM patch, and is only intended to be used to save some local
|
||||||
DOM state. Also, it will not be called if the widget is not in the DOM (this can
|
DOM state. Also, it will not be called if the widget is not in the DOM (this can
|
||||||
happen with widgets with `t-keepalive`).
|
happen with widgets with `t-keepalive`).
|
||||||
|
|
||||||
The return value of this method will be given as the first argument of the
|
The return value of this method will be given as the first argument of the
|
||||||
@@ -320,7 +319,7 @@ likely via a change in its state/props or environment).
|
|||||||
|
|
||||||
This method is not called on the initial render. It is useful to interact
|
This method is not called on the initial render. It is useful to interact
|
||||||
with the DOM (for example, through an external library) whenever the
|
with the DOM (for example, through an external library) whenever the
|
||||||
component was patched. Note that this hook will not be called if the widget is
|
component was patched. Note that this hook will not be called if the widget is
|
||||||
not in the DOM (this can happen with widgets with `t-keepalive`).
|
not in the DOM (this can happen with widgets with `t-keepalive`).
|
||||||
|
|
||||||
The `snapshot` parameter is the result of the previous `willPatch` call.
|
The `snapshot` parameter is the result of the previous `willPatch` call.
|
||||||
@@ -345,3 +344,89 @@ the DOM. This is a good place to remove some listeners, for example.
|
|||||||
```
|
```
|
||||||
|
|
||||||
This is the opposite method of `mounted`.
|
This is the opposite method of `mounted`.
|
||||||
|
|
||||||
|
### Semantics
|
||||||
|
|
||||||
|
We give here an informal description of the way components are created/updated
|
||||||
|
in an application. Here, ordered lists describe actions that are executed
|
||||||
|
sequentially, bullet lists describe actions that are executed in parallel.
|
||||||
|
|
||||||
|
**Scenario 1: Initial Mounting** Imagine we want to render the following component tree:
|
||||||
|
|
||||||
|
```
|
||||||
|
A
|
||||||
|
/ \
|
||||||
|
B C
|
||||||
|
/ \
|
||||||
|
D E
|
||||||
|
```
|
||||||
|
|
||||||
|
Here is what happen whenever we mount the root
|
||||||
|
component (with some code like `app.mount(document.body)`).
|
||||||
|
|
||||||
|
1. `willStart` is called on `A`
|
||||||
|
|
||||||
|
2. when it is done, template `A` is rendered.
|
||||||
|
|
||||||
|
- widget `B` is created
|
||||||
|
1. `willStart` is called on `B`
|
||||||
|
2. template `B` is rendered
|
||||||
|
- widget `C` is created
|
||||||
|
1. `willStart` is called on `C`
|
||||||
|
2. template `C` is rendered
|
||||||
|
- widget `D` is created
|
||||||
|
1. `willStart` is called on `D`
|
||||||
|
2. template `D` is rendered
|
||||||
|
- widget `E` is created
|
||||||
|
1. `willStart` is called on `E`
|
||||||
|
2. template `E` is rendered
|
||||||
|
|
||||||
|
3. widget `A` is patched into a detached DOM element. This will create the actual
|
||||||
|
widget `A` DOM structure. The patching process will cause recursively the
|
||||||
|
patching of the `B`, `C`, `D` and `E` DOM trees. (so the actual full DOM tree is created
|
||||||
|
in one pass)
|
||||||
|
|
||||||
|
4. the widget `A` root element is actually appended to `document.body`
|
||||||
|
|
||||||
|
5. The method `mounted` is called recursively on all widgets in the following
|
||||||
|
order: `B`, `D`, `E`, `C`, `A`.
|
||||||
|
|
||||||
|
**Scenario 2: state change, rerendering**. Now, let's assume that the user clicked on some
|
||||||
|
button in `C`, and this results in a state update, which is supposed to:
|
||||||
|
|
||||||
|
- update `D`,
|
||||||
|
- remove `E`,
|
||||||
|
- add new widget `F`.
|
||||||
|
|
||||||
|
So, the component tree should look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
A
|
||||||
|
/ \
|
||||||
|
B C
|
||||||
|
/ \
|
||||||
|
D F
|
||||||
|
```
|
||||||
|
|
||||||
|
Here is what Owl will do:
|
||||||
|
|
||||||
|
1. because of a state change, the method `render` is called on `C`
|
||||||
|
2. template `C` is rendered again
|
||||||
|
|
||||||
|
- widget `D` is updated:
|
||||||
|
1. hook `willUpdateProps` is called on `D` (async)
|
||||||
|
2. template `D` is rerendered
|
||||||
|
- widget `F` is created:
|
||||||
|
1. hook `willStart` is called on `E` (async)
|
||||||
|
2. template `F` is rerendered
|
||||||
|
|
||||||
|
3. `willPatch` hooks are called recursively on widgets `C`, `D` (not on `F`,
|
||||||
|
because it is not mounted yet)
|
||||||
|
|
||||||
|
4. widget `C` is patched, which will cause recursively:
|
||||||
|
|
||||||
|
1. patching of `D`,
|
||||||
|
2. `willUnmount` hook on `E`, then destruction of `E`,
|
||||||
|
3. (initial) patching of `F`, then hook `mounted` is called on `F`
|
||||||
|
|
||||||
|
5. `patched` hooks are called on `D`, `C`
|
||||||
|
|||||||
Reference in New Issue
Block a user