[DOC] doc: miscellaneous formatting updates

This commit is contained in:
Géry Debongnie
2019-06-14 15:24:04 +02:00
parent 1f0457f69b
commit b9fae87273
10 changed files with 153 additions and 155 deletions
+10 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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).