mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[DOC] doc: miscellaneous formatting updates
This commit is contained in:
@@ -10,7 +10,7 @@ other Odoo related projects. OWL's main feature is a _declarative component syst
|
|||||||
|
|
||||||
**Try it online!** An online playground is available at [https://odoo.github.io/owl/playground](https://odoo.github.io/owl/playground) to let you experiment with the OWL framework.
|
**Try it online!** An online playground is available at [https://odoo.github.io/owl/playground](https://odoo.github.io/owl/playground) to let you experiment with the OWL framework.
|
||||||
|
|
||||||
## OWL's design principles
|
## OWL's Design Principles
|
||||||
|
|
||||||
OWL is designed to be used in highly dynamic applications where changing
|
OWL is designed to be used in highly dynamic applications where changing
|
||||||
requirements are common, code needs to be maintained by large teams.
|
requirements are common, code needs to be maintained by large teams.
|
||||||
@@ -30,7 +30,7 @@ Owl is not designed to be fast or small (even though it is quite good on those
|
|||||||
two topics). If you are interested in a comparison with React or Vue, you will
|
two topics). If you are interested in a comparison with React or Vue, you will
|
||||||
find some more information [here](doc/comparison.md).
|
find some more information [here](doc/comparison.md).
|
||||||
|
|
||||||
# Example
|
## Example
|
||||||
|
|
||||||
Here is a short example to illustrate interactive widgets:
|
Here is a short example to illustrate interactive widgets:
|
||||||
|
|
||||||
@@ -64,15 +64,15 @@ If you want to use a simple `<script>` tag, the last release can be downloaded h
|
|||||||
|
|
||||||
Some npm scripts are available:
|
Some npm scripts are available:
|
||||||
|
|
||||||
| Command | Description |
|
| Command | Description |
|
||||||
| ---------------------- | ------------------------------------------------------------------------------- |
|
| --------------------- | ---------------------------------------------------------------------------- |
|
||||||
| `npm install` | install every dependency required for this project |
|
| `npm install` | install every dependency required for this project |
|
||||||
| `npm run build` | build a bundle of _owl_ in the _/dist/_ folder |
|
| `npm run build` | build a bundle of _owl_ in the _/dist/_ folder |
|
||||||
| `npm run minify` | minify the prebuilt owl.js file |
|
| `npm run minify` | minify the prebuilt owl.js file |
|
||||||
| `npm run test` | run all tests |
|
| `npm run test` | run all tests |
|
||||||
| `npm run test:watch` | run all tests, and keep a watcher |
|
| `npm run test:watch` | run all tests, and keep a watcher |
|
||||||
| `npm run tools` | build tools applications, start a static server (see [here](doc/tooling.md)) |
|
| `npm run tools` | build tools applications, start a static server (see [here](doc/tooling.md)) |
|
||||||
| `npm run tools:watch` | same as `tools`, but with a watcher to rebuild owl |
|
| `npm run tools:watch` | same as `tools`, but with a watcher to rebuild owl |
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
|
|||||||
+8
-6
@@ -7,6 +7,8 @@ In this page, we try to highlight some of these differences. Obviously, some
|
|||||||
effort was done to be fair. However, if you disagree with some of the points
|
effort was done to be fair. However, if you disagree with some of the points
|
||||||
discussed, feel free to open an issue/submit a PR to correct this text.
|
discussed, feel free to open an issue/submit a PR to correct this text.
|
||||||
|
|
||||||
|
## Content
|
||||||
|
|
||||||
- [Size](#size)
|
- [Size](#size)
|
||||||
- [Tooling/Build Step](#toolingbuild-step)
|
- [Tooling/Build Step](#toolingbuild-step)
|
||||||
- [Templating](#templating)
|
- [Templating](#templating)
|
||||||
@@ -14,7 +16,7 @@ discussed, feel free to open an issue/submit a PR to correct this text.
|
|||||||
- [Reactiveness](#reactiveness)
|
- [Reactiveness](#reactiveness)
|
||||||
- [State Management](#state-management)
|
- [State Management](#state-management)
|
||||||
|
|
||||||
### Size
|
## Size
|
||||||
|
|
||||||
OWL is intended to be small and to work at a slightly lower level of abstraction
|
OWL is intended to be small and to work at a slightly lower level of abstraction
|
||||||
than React and Vue. Also, jQuery is not the same kind of framework, but it is interesting to compare.
|
than React and Vue. Also, jQuery is not the same kind of framework, but it is interesting to compare.
|
||||||
@@ -26,7 +28,7 @@ than React and Vue. Also, jQuery is not the same kind of framework, but it is in
|
|||||||
| React + ReactDOM + Redux | | 40kb |
|
| React + ReactDOM + Redux | | 40kb |
|
||||||
| jQuery | 86kb | 30kb |
|
| jQuery | 86kb | 30kb |
|
||||||
|
|
||||||
### Tooling/Build step
|
## Tooling/Build step
|
||||||
|
|
||||||
OWL is designed to be easy to use in a standalone way. For various reasons,
|
OWL is designed to be easy to use in a standalone way. For various reasons,
|
||||||
Odoo does not want to rely on standard web tools (such as webpack), and OWL can
|
Odoo does not want to rely on standard web tools (such as webpack), and OWL can
|
||||||
@@ -84,7 +86,7 @@ This has the advantage of having the full power of Javascript, but is less
|
|||||||
structured than a template language. Note that the tooling is quite impressive:
|
structured than a template language. Note that the tooling is quite impressive:
|
||||||
there is a syntax highlighter for jsx here on github!
|
there is a syntax highlighter for jsx here on github!
|
||||||
|
|
||||||
### Asynchronous rendering
|
## Asynchronous Rendering
|
||||||
|
|
||||||
This is actually a big difference between OWL and React/Vue: components in OWL
|
This is actually a big difference between OWL and React/Vue: components in OWL
|
||||||
are totally asynchronous. They have two asynchronous hooks in their lifecycle:
|
are totally asynchronous. They have two asynchronous hooks in their lifecycle:
|
||||||
@@ -115,7 +117,7 @@ extremely powerful as well, as demonstrated by the Odoo Web Client.
|
|||||||
Lazy loading static libraries can obviously be done with React/Vue, but it is
|
Lazy loading static libraries can obviously be done with React/Vue, but it is
|
||||||
more convoluted.
|
more convoluted.
|
||||||
|
|
||||||
### Reactiveness
|
## Reactiveness
|
||||||
|
|
||||||
React has a simple model: whenever the state changes, it is
|
React has a simple model: whenever the state changes, it is
|
||||||
replaced with a new state (via the setState method). Then, the DOM is patched.
|
replaced with a new state (via the setState method). Then, the DOM is patched.
|
||||||
@@ -129,7 +131,7 @@ Owl is closer to vue: it also tracks magically the state properties, but it does
|
|||||||
only increment a counter whenever it changes (and a _deep_ counter for each of
|
only increment a counter whenever it changes (and a _deep_ counter for each of
|
||||||
its parents). This assumes that the state is actually a tree.
|
its parents). This assumes that the state is actually a tree.
|
||||||
|
|
||||||
### State Management
|
## State Management
|
||||||
|
|
||||||
Managing the state of an application is a tricky issue. Many solutions have
|
Managing the state of an application is a tricky issue. Many solutions have
|
||||||
been proposed these last few years. It also depends on the kind of application we
|
been proposed these last few years. It also depends on the kind of application we
|
||||||
@@ -190,5 +192,5 @@ keeps track of who get data, and retrigger a render when it was changed.
|
|||||||
|
|
||||||
Owl store is a little bit like a mix of redux and vuex: it has mutations and
|
Owl store is a little bit like a mix of redux and vuex: it has mutations and
|
||||||
actions, like VueX, it keeps track of the state changes, but it does not notify
|
actions, like VueX, it keeps track of the state changes, but it does not notify
|
||||||
a component when the state changes. Instead, components need to connect to the
|
a component when the state changes. Instead, components need to connect to the
|
||||||
store like in redux, with a function that will listen to the relevant state.
|
store like in redux, with a function that will listen to the relevant state.
|
||||||
|
|||||||
+11
-11
@@ -10,16 +10,16 @@
|
|||||||
- [Methods](#methods)
|
- [Methods](#methods)
|
||||||
- [Lifecycle](#lifecycle)
|
- [Lifecycle](#lifecycle)
|
||||||
- [Composition](#composition)
|
- [Composition](#composition)
|
||||||
- [Asynchronous rendering](#asynchronous-rendering)
|
- [Asynchronous Rendering](#asynchronous-rendering)
|
||||||
- [Event Handling](#event-handling)
|
- [Event Handling](#event-handling)
|
||||||
- [`t-key` directive](#t-key-directive)
|
- [`t-key` Directive](#t-key-directive)
|
||||||
- [`t-mounted` directive](#t-mounted-directive)
|
- [`t-mounted` Directive](#t-mounted-directive)
|
||||||
- [Semantics](#semantics)
|
- [Semantics](#semantics)
|
||||||
- [Props Validation](#props-validation)
|
- [Props Validation](#props-validation)
|
||||||
- [Keeping References](#keeping-references)
|
- [References](#references)
|
||||||
- [Slots](#slots)
|
- [Slots](#slots)
|
||||||
- [Form input bindings](#form-input-bindings)
|
- [Form Input Bindings](#form-input-bindings)
|
||||||
- [Asynchronous rendering](#asynchronous-rendering)
|
- [Asynchronous Rendering](#asynchronous-rendering)
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@@ -410,7 +410,7 @@ with a class object:
|
|||||||
<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}" />
|
||||||
```
|
```
|
||||||
|
|
||||||
### Event handling
|
### Event Handling
|
||||||
|
|
||||||
In a component's template, it is useful to be able to register handlers on some
|
In a component's template, it is useful to be able to register handlers on some
|
||||||
elements to some specific events. This is what makes a template _alive_. There
|
elements to some specific events. This is what makes a template _alive_. There
|
||||||
@@ -496,7 +496,7 @@ The `t-on` directive also allows to prebind some arguments. For example,
|
|||||||
Here, `expr` is a valid Owl expression, so it could be `true` or some variable
|
Here, `expr` is a valid Owl expression, so it could be `true` or some variable
|
||||||
from the rendering context.
|
from the rendering context.
|
||||||
|
|
||||||
### `t-key` directive
|
### `t-key` Directive
|
||||||
|
|
||||||
Even though Owl tries to be as declarative as possible, some DOM state is still
|
Even though Owl tries to be as declarative as possible, some DOM state is still
|
||||||
locked inside the DOM: for example, the scrolling state, the current user selection,
|
locked inside the DOM: for example, the scrolling state, the current user selection,
|
||||||
@@ -520,7 +520,7 @@ There are three main use cases:
|
|||||||
- _animations_: give a different identity to a component. Ex: thread id with
|
- _animations_: give a different identity to a component. Ex: thread id with
|
||||||
animations on add/remove message.
|
animations on add/remove message.
|
||||||
|
|
||||||
### `t-mounted` directive
|
### `t-mounted` Directive
|
||||||
|
|
||||||
The `t-mounted` directive allows to register a callback to execute whenever the node
|
The `t-mounted` directive allows to register a callback to execute whenever the node
|
||||||
is inserted into the DOM.
|
is inserted into the DOM.
|
||||||
@@ -712,7 +712,7 @@ Examples:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### Keeping references
|
### References
|
||||||
|
|
||||||
The `t-ref` directive helps a component keep reference to some inside part of it.
|
The `t-ref` directive helps a component keep reference to some inside part of it.
|
||||||
Like the `t-on` directive, it can work either on a DOM node, or on a component:
|
Like the `t-on` directive, it can work either on a DOM node, or on a component:
|
||||||
@@ -904,7 +904,7 @@ update a number whenever the change is done.
|
|||||||
|
|
||||||
Note: the online playground has an example to show how it works.
|
Note: the online playground has an example to show how it works.
|
||||||
|
|
||||||
### Asynchronous rendering
|
### Asynchronous Rendering
|
||||||
|
|
||||||
Working with asynchronous code always adds a lot of complexity to a system. Whenever
|
Working with asynchronous code always adds a lot of complexity to a system. Whenever
|
||||||
different parts of a system are active at the same time, one needs to think
|
different parts of a system are active at the same time, one needs to think
|
||||||
|
|||||||
+16
-16
@@ -30,21 +30,21 @@ In those situations, we need a way to tell the observer that something happened.
|
|||||||
This can be done by using the `set` and `delete` (only for objects) static
|
This can be done by using the `set` and `delete` (only for objects) static
|
||||||
methods of the `Observer`.
|
methods of the `Observer`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const observer = new owl.Observer();
|
const observer = new owl.Observer();
|
||||||
const obj = { a: 1 };
|
const obj = { a: 1 };
|
||||||
observer.observe(obj);
|
observer.observe(obj);
|
||||||
obj.b = 2; // won't notify the change
|
obj.b = 2; // won't notify the change
|
||||||
owl.Observer.set(obj, "b", 2); // will notify the change
|
owl.Observer.set(obj, "b", 2); // will notify the change
|
||||||
|
|
||||||
delete obj.b; // won't notify the change
|
delete obj.b; // won't notify the change
|
||||||
owl.Observer.delete(obj, "b"); // will notify the change
|
owl.Observer.delete(obj, "b"); // will notify the change
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const observer = new owl.Observer();
|
const observer = new owl.Observer();
|
||||||
const arr = ["a"];
|
const arr = ["a"];
|
||||||
observer.observe(arr);
|
observer.observe(arr);
|
||||||
arr[0] = "b"; // won't notify the change
|
arr[0] = "b"; // won't notify the change
|
||||||
owl.Observer.set(arr, 0, "b"); // will notify the change
|
owl.Observer.set(arr, 0, "b"); // will notify the change
|
||||||
```
|
```
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# 🦉 Quick Start 🦉
|
# 🦉 Quick Start 🦉
|
||||||
|
|
||||||
## Static server
|
## Static Server
|
||||||
|
|
||||||
Let us assume that we have a static server running somewhere. We could then
|
Let us assume that we have a static server running somewhere. We could then
|
||||||
simply add an html page with a few extra files.
|
simply add an html page with a few extra files.
|
||||||
|
|||||||
+20
-20
@@ -6,14 +6,14 @@
|
|||||||
- [Directives](#directives)
|
- [Directives](#directives)
|
||||||
- [QWeb Engine](#qweb-engine)
|
- [QWeb Engine](#qweb-engine)
|
||||||
- [Reference](#reference)
|
- [Reference](#reference)
|
||||||
- [White spaces](#white-spaces)
|
- [White Spaces](#white-spaces)
|
||||||
- [Root nodes](#root-nodes)
|
- [Root Nodes](#root-nodes)
|
||||||
- [Expression evaluation](#expression-evaluation)
|
- [Expression Evaluation](#expression-evaluation)
|
||||||
- [Static html nodes](#static-html-nodes)
|
- [Static html Nodes](#static-html-nodes)
|
||||||
- [Outputting data](#outputting-data)
|
- [Outputting Data](#outputting-data)
|
||||||
- [Setting Variables](#setting-variables)
|
- [Setting Variables](#setting-variables)
|
||||||
- [Conditionals](#conditionals)
|
- [Conditionals](#conditionals)
|
||||||
- [Dynamic attributes](#dynamic-attributes)
|
- [Dynamic Attributes](#dynamic-attributes)
|
||||||
- [Loops](#loops)
|
- [Loops](#loops)
|
||||||
- [Rendering Sub Templates](#rendering-sub-templates)
|
- [Rendering Sub Templates](#rendering-sub-templates)
|
||||||
- [Debugging](#debugging)
|
- [Debugging](#debugging)
|
||||||
@@ -65,16 +65,16 @@ We present here a list of all standard QWeb directives:
|
|||||||
The component system in Owl requires additional directives, to express various
|
The component system in Owl requires additional directives, to express various
|
||||||
needs. Here is a list of all Owl specific directives:
|
needs. Here is a list of all Owl specific directives:
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| ------------------------------------ | --------------------------------------------------------------------------------------- |
|
| ------------------------------------ | ----------------------------------------------------------------------------------- |
|
||||||
| `t-widget`, `t-keepalive`, `t-async` | [Defining a sub component](component.md#composition) |
|
| `t-widget`, `t-keepalive`, `t-async` | [Defining a sub component](component.md#composition) |
|
||||||
| `t-ref` | [Setting a reference to a dom node or a sub component](component.md#keeping-references) |
|
| `t-ref` | [Setting a reference to a dom node or a sub component](component.md#references) |
|
||||||
| `t-key` | [Defining a key (to help virtual dom reconciliation)](component.md#t-key-directive) |
|
| `t-key` | [Defining a key (to help virtual dom reconciliation)](component.md#t-key-directive) |
|
||||||
| `t-on-*` | [Event handling](component.md#event-handling) |
|
| `t-on-*` | [Event handling](component.md#event-handling) |
|
||||||
| `t-transition` | [Defining an animation](animations.md#css-transitions) |
|
| `t-transition` | [Defining an animation](animations.md#css-transitions) |
|
||||||
| `t-mounted` | [Callback when a node or component is mounted](component.md#t-mounted-directive) |
|
| `t-mounted` | [Callback when a node or component is mounted](component.md#t-mounted-directive) |
|
||||||
| `t-slot` | [Rendering a slot](component.md#slots) |
|
| `t-slot` | [Rendering a slot](component.md#slots) |
|
||||||
| `t-model` | [Form input bindings](component.md#form-input-bindings) |
|
| `t-model` | [Form input bindings](component.md#form-input-bindings) |
|
||||||
|
|
||||||
## QWeb Engine
|
## QWeb Engine
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ We define in this section the specification of how `QWeb` templates should be
|
|||||||
rendered. Note that we only document here the standard QWeb specification. Owl
|
rendered. Note that we only document here the standard QWeb specification. Owl
|
||||||
specific extensions are documented in various other parts of the documentation.
|
specific extensions are documented in various other parts of the documentation.
|
||||||
|
|
||||||
### White spaces
|
### White Spaces
|
||||||
|
|
||||||
White spaces in a templates are handled in a special way:
|
White spaces in a templates are handled in a special way:
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ White spaces in a templates are handled in a special way:
|
|||||||
- if a whitespace-only text node contains a linebreak, it is ignored
|
- if a whitespace-only text node contains a linebreak, it is ignored
|
||||||
- the previous rules do not apply if we are in a `<pre>` tag
|
- the previous rules do not apply if we are in a `<pre>` tag
|
||||||
|
|
||||||
### Root nodes
|
### Root Nodes
|
||||||
|
|
||||||
For many reasons, Owl QWeb templates should have a single root node. More
|
For many reasons, Owl QWeb templates should have a single root node. More
|
||||||
precisely, the result of a template rendering should have a single root node:
|
precisely, the result of a template rendering should have a single root node:
|
||||||
@@ -175,7 +175,7 @@ Note: this does not apply to subtemplates (see the `t-call` directive). In that
|
|||||||
case, they will be inlined in the main template, and can actually have many
|
case, they will be inlined in the main template, and can actually have many
|
||||||
root nodes.
|
root nodes.
|
||||||
|
|
||||||
### Expression evaluation
|
### Expression Evaluation
|
||||||
|
|
||||||
QWeb expressions are strings that will be processed at compile time. Each variable in
|
QWeb expressions are strings that will be processed at compile time. Each variable in
|
||||||
the javascript expression will be replaced by a lookup in the context (so, the
|
the javascript expression will be replaced by a lookup in the context (so, the
|
||||||
@@ -345,7 +345,7 @@ Extra conditional branching directives `t-elif` and `t-else` are also available:
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Dynamic attributes
|
### Dynamic Attributes
|
||||||
|
|
||||||
One can use the `t-att-` directive to add dynamic attributes. Its main use is to
|
One can use the `t-att-` directive to add dynamic attributes. Its main use is to
|
||||||
evaluate an expression (at rendering time) and bind an attribute to its result:
|
evaluate an expression (at rendering time) and bind an attribute to its result:
|
||||||
|
|||||||
+1
-2
@@ -1,6 +1,5 @@
|
|||||||
# 🦉 OWL Documentation 🦉
|
# 🦉 OWL Documentation 🦉
|
||||||
|
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
- [Animations](animations.md)
|
- [Animations](animations.md)
|
||||||
@@ -12,7 +11,7 @@
|
|||||||
- [Utils](utils.md)
|
- [Utils](utils.md)
|
||||||
- [Virtual DOM](vdom.md)
|
- [Virtual DOM](vdom.md)
|
||||||
|
|
||||||
## Learning resources
|
## Learning Resources
|
||||||
|
|
||||||
- [Quick Start](quick_start.md)
|
- [Quick Start](quick_start.md)
|
||||||
|
|
||||||
|
|||||||
+69
-69
@@ -9,7 +9,7 @@
|
|||||||
- [Mutations](#mutations)
|
- [Mutations](#mutations)
|
||||||
- [Actions](#actions)
|
- [Actions](#actions)
|
||||||
- [Getters](#getters)
|
- [Getters](#getters)
|
||||||
- [Connecting a component](#connecting-a-component)
|
- [Connecting a Component](#connecting-a-component)
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@@ -32,46 +32,45 @@ Here is what a simple store looks like:
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const actions = {
|
const actions = {
|
||||||
addTodo({commit}, message) {
|
addTodo({ commit }, message) {
|
||||||
commit('addTodo', message);
|
commit("addTodo", message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
addTodo({state}, message) {
|
addTodo({ state }, message) {
|
||||||
const todo = {
|
const todo = {
|
||||||
id: state.nextId++,
|
id: state.nextId++,
|
||||||
message,
|
message,
|
||||||
isCompleted: false,
|
isCompleted: false
|
||||||
};
|
};
|
||||||
state.todos.push(todo);
|
state.todos.push(todo);
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
todos: [],
|
todos: [],
|
||||||
nextId: 1,
|
nextId: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
const store = new owl.Store({state, actions, mutations});
|
const store = new owl.Store({ state, actions, mutations });
|
||||||
store.on('update', () => console.log(store.state));
|
store.on("update", () => console.log(store.state));
|
||||||
|
|
||||||
// updating the state
|
// updating the state
|
||||||
store.dispatch('addTodo', 'fix all bugs');
|
store.dispatch("addTodo", "fix all bugs");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
The store is a simple [`owl.EventBus`](event_bus.md) that triggers `update` events whenever its
|
The store is a simple [`owl.EventBus`](event_bus.md) that triggers `update` events whenever its
|
||||||
state is changed. Note that these events are triggered only after a microtask
|
state is changed. Note that these events are triggered only after a microtask
|
||||||
tick, so only one event will be triggered for any number of state changes in a
|
tick, so only one event will be triggered for any number of state changes in a
|
||||||
call stack.
|
call stack.
|
||||||
|
|
||||||
Also, it is important to mention that the state is observed (with an `owl.Observer`),
|
Also, it is important to mention that the state is observed (with an `owl.Observer`),
|
||||||
which is the reason why it is able to know if it was changed. This implies that
|
which is the reason why it is able to know if it was changed. This implies that
|
||||||
state changes need to be done carefully in some cases (adding a new key to an
|
state changes need to be done carefully in some cases (adding a new key to an
|
||||||
object, or modifying an array with the `arr[i] = newValue` syntax). See the
|
object, or modifying an array with the `arr[i] = newValue` syntax). See the
|
||||||
[Observer](observer.md)'s documentation for more details.
|
[Observer](observer.md)'s documentation for more details.
|
||||||
|
|
||||||
### Public API
|
### Public API
|
||||||
@@ -82,26 +81,26 @@ object, or modifying an array with the `arr[i] = newValue` syntax). See the
|
|||||||
|
|
||||||
### Mutations
|
### Mutations
|
||||||
|
|
||||||
Mutations are the only way to modify the state. Changing the state outside a
|
Mutations are the only way to modify the state. Changing the state outside a
|
||||||
mutation is not allowed (and should throw an error). Mutations are synchronous.
|
mutation is not allowed (and should throw an error). Mutations are synchronous.
|
||||||
|
|
||||||
### Actions
|
### Actions
|
||||||
|
|
||||||
Actions are used to coordinate state changes. It is also useful whenever some
|
Actions are used to coordinate state changes. It is also useful whenever some
|
||||||
asynchronous logic is necessary. For example, fetching data should be done
|
asynchronous logic is necessary. For example, fetching data should be done
|
||||||
in an action.
|
in an action.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const actions = {
|
const actions = {
|
||||||
async login({commit}) {
|
async login({ commit }) {
|
||||||
commit('setLoginState', 'pending');
|
commit("setLoginState", "pending");
|
||||||
try {
|
try {
|
||||||
const loginInfo = await doSomeRPC('/login/', 'someinfo');
|
const loginInfo = await doSomeRPC("/login/", "someinfo");
|
||||||
commit('setLoginState', loginInfo);
|
commit("setLoginState", loginInfo);
|
||||||
} catch {
|
} catch {
|
||||||
commit('setLoginState', 'error');
|
commit("setLoginState", "error");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -128,23 +127,22 @@ transform the data contained in the store.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const getters = {
|
const getters = {
|
||||||
getPost({state}, id) {
|
getPost({ state }, id) {
|
||||||
const post = state.posts.find(p => p.id === id);
|
const post = state.posts.find(p => p.id === id);
|
||||||
const author = state.authors.find(a => a.id = post.id);
|
const author = state.authors.find(a => (a.id = post.id));
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
author,
|
author,
|
||||||
content: post.content
|
content: post.content
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// somewhere else
|
// somewhere else
|
||||||
const post = store.getters.getPost(id);
|
const post = store.getters.getPost(id);
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Connecting a component
|
### Connecting a Component
|
||||||
|
|
||||||
By default, an Owl `Component` is not connected to any store. The `connect`
|
By default, an Owl `Component` is not connected to any store. The `connect`
|
||||||
function is there to create sub Components that are connected versions of
|
function is there to create sub Components that are connected versions of
|
||||||
@@ -152,34 +150,35 @@ Components.
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const actions = {
|
const actions = {
|
||||||
increment({commit}) {
|
increment({ commit }) {
|
||||||
commit('increment', 1);
|
commit("increment", 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const mutations = {
|
const mutations = {
|
||||||
increment({state}, val) {
|
increment({ state }, val) {
|
||||||
state.counter += val;
|
state.counter += val;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const state = {
|
const state = {
|
||||||
counter: 0,
|
counter: 0
|
||||||
};
|
};
|
||||||
const store = new owl.Store({state, actions, mutations});
|
const store = new owl.Store({ state, actions, mutations });
|
||||||
|
|
||||||
class Counter extends owl.Component {
|
class Counter extends owl.Component {
|
||||||
increment() {
|
increment() {
|
||||||
this.env.store.dispatch('increment');
|
this.env.store.dispatch("increment");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function mapStoreToProps(state) {
|
function mapStoreToProps(state) {
|
||||||
return {
|
return {
|
||||||
value: state.counter
|
value: state.counter
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const ConnectedCounter = owl.connect(Counter, mapStoreToProps);
|
const ConnectedCounter = owl.connect(Counter, mapStoreToProps);
|
||||||
|
|
||||||
const counter = new ConnectedCounter({ store, qweb });
|
const counter = new ConnectedCounter({ store, qweb });
|
||||||
```
|
```
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<button t-name="Counter" t-on-click="increment">
|
<button t-name="Counter" t-on-click="increment">
|
||||||
Click Me! [<t t-esc="props.value"/>]
|
Click Me! [<t t-esc="props.value"/>]
|
||||||
@@ -187,17 +186,18 @@ const counter = new ConnectedCounter({ store, qweb });
|
|||||||
```
|
```
|
||||||
|
|
||||||
The arguments of `connect` are:
|
The arguments of `connect` are:
|
||||||
- `Counter`: an owl `Component` to connect
|
|
||||||
- `mapStoreToProps`: a function that extracts the `props` of the Component
|
- `Counter`: an owl `Component` to connect
|
||||||
from the `state` of the `Store` and returns them as a dict
|
- `mapStoreToProps`: a function that extracts the `props` of the Component
|
||||||
- `options`: dictionary of optional parameters that may contain
|
from the `state` of the `Store` and returns them as a dict
|
||||||
- `getStore`: a function that takes the `env` in arguments and returns an
|
- `options`: dictionary of optional parameters that may contain
|
||||||
instance of `Store` to connect to (if not given, connects to `env.store`)
|
- `getStore`: a function that takes the `env` in arguments and returns an
|
||||||
- `hashFunction`: the function to use to detect changes in the state (if not
|
instance of `Store` to connect to (if not given, connects to `env.store`)
|
||||||
given, generates a function that uses revision numbers, incremented at
|
- `hashFunction`: the function to use to detect changes in the state (if not
|
||||||
each state change)
|
given, generates a function that uses revision numbers, incremented at
|
||||||
- `deep`: [only useful if no hashFunction is given] if false, only watch
|
each state change)
|
||||||
for top level state changes (true by default)
|
- `deep`: [only useful if no hashFunction is given] if false, only watch
|
||||||
|
for top level state changes (true by default)
|
||||||
|
|
||||||
The `connect` function returns a sub class of the given `Component` which is
|
The `connect` function returns a sub class of the given `Component` which is
|
||||||
connected to the `store`.
|
connected to the `store`.
|
||||||
|
|||||||
+16
-16
@@ -18,34 +18,35 @@ not ready yet, resolved directly otherwise). If called with a callback as
|
|||||||
argument, it executes it as soon as the DOM ready (or directly).
|
argument, it executes it as soon as the DOM ready (or directly).
|
||||||
|
|
||||||
```js
|
```js
|
||||||
Promise.all([loadTemplates(), owl.utils.whenReady()]).then(function ([templates]) {
|
Promise.all([loadTemplates(), owl.utils.whenReady()]).then(function([
|
||||||
const qweb = new owl.QWeb(templates);
|
templates
|
||||||
const app = new App({ qweb });
|
]) {
|
||||||
app.mount(document.body);
|
const qweb = new owl.QWeb(templates);
|
||||||
|
const app = new App({ qweb });
|
||||||
|
app.mount(document.body);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
owl.utils.whenReady(function() {
|
owl.utils.whenReady(function() {
|
||||||
const qweb = new owl.QWeb();
|
const qweb = new owl.QWeb();
|
||||||
const app = new App({ qweb });
|
const app = new App({ qweb });
|
||||||
app.mount(document.body);
|
app.mount(document.body);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## `loadJS`
|
## `loadJS`
|
||||||
|
|
||||||
`loadJS` takes a url (string) for a javascript resource, and loads it. It returns
|
`loadJS` takes a url (string) for a javascript resource, and loads it. It returns
|
||||||
a promise, so the caller can properly react when it is ready. Also, it is smart:
|
a promise, so the caller can properly react when it is ready. Also, it is smart:
|
||||||
it maintains a list of urls previously loaded (or currently being loaded), and
|
it maintains a list of urls previously loaded (or currently being loaded), and
|
||||||
prevent doing twice the work.
|
prevent doing twice the work.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
class MyComponent extends owl.Component {
|
class MyComponent extends owl.Component {
|
||||||
willStart() {
|
willStart() {
|
||||||
return owl.utils.loadJS('/static/libs/someLib.js');
|
return owl.utils.loadJS("/static/libs/someLib.js");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -53,13 +54,12 @@ class MyComponent extends owl.Component {
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
async function makeEnv() {
|
async function makeEnv() {
|
||||||
const templates = await owl.utils.loadTemplates('templates.xml');
|
const templates = await owl.utils.loadTemplates("templates.xml");
|
||||||
const qweb = new owl.QWeb(templates);
|
const qweb = new owl.QWeb(templates);
|
||||||
return { qweb };
|
return { qweb };
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `escape`
|
## `escape`
|
||||||
|
|
||||||
|
|
||||||
## `debounce`
|
## `debounce`
|
||||||
|
|||||||
+1
-4
@@ -1,11 +1,10 @@
|
|||||||
# 🦉 VDom 🦉
|
# 🦉 VDom 🦉
|
||||||
|
|
||||||
Owl is a declarative component system: we declare the structure of the component
|
Owl is a declarative component system: we declare the structure of the component
|
||||||
tree, and Owl will translate that to a list of imperative operations. This
|
tree, and Owl will translate that to a list of imperative operations. This
|
||||||
translation is done by a virtual dom. This is the low level layer of Owl, most
|
translation is done by a virtual dom. This is the low level layer of Owl, most
|
||||||
developer will not need to call directly the virtual dom functions.
|
developer will not need to call directly the virtual dom functions.
|
||||||
|
|
||||||
|
|
||||||
The main idea behind a virtual dom is to keep a in-memory representation of the
|
The main idea behind a virtual dom is to keep a in-memory representation of the
|
||||||
DOM (called a virtual node), and whenever some change is needed, to regenerate
|
DOM (called a virtual node), and whenever some change is needed, to regenerate
|
||||||
a new representation, compute the difference between the old and the new, then
|
a new representation, compute the difference between the old and the new, then
|
||||||
@@ -17,5 +16,3 @@ apply the changes.
|
|||||||
- `patch`: compare two virtual nodes, and apply the difference.
|
- `patch`: compare two virtual nodes, and apply the difference.
|
||||||
|
|
||||||
Note: Owl's virtual dom is a fork of [snabbdom](https://github.com/snabbdom/snabbdom).
|
Note: Owl's virtual dom is a fork of [snabbdom](https://github.com/snabbdom/snabbdom).
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user