原文链接:https://www.alanhou.org/odoo-14-owl-todolist/

1、组件树

Root

        /   \
       A     B
      / \
     C   D
 
2、状态(state):各组件可管理其自身的本地状态。这是一个简单的ES6类,没有特殊规则:
const { Component, useState } = owl;
const { xml } = owl.tags; class Counter extends Component {
static template = xml`
<button t-on-click="state.value++">
Click Me! [<t t-esc="state.value"/>]
</button>`; state = useState({ value: 0 });
} class App extends Component {
static template = xml`
<div>
<span>Hello Owl</span>
<Counter />
</div>`; static components = { Counter };
} const app = new App();
app.mount(document.body);

  

owl_todoapp

(function () {
const {Component, Store} = owl; //
const {xml} = owl.tags; //用来插入xml代码片段的
const {whenReady} = owl.utils; //工具类
const {useRef, useDispatch, useState, useStore} = owl.hooks; //钩子 // -------------------------------------------------------------------------
// Store
// -------------------------------------------------------------------------
const actions = {
addTask({state}, title) {
title = title.trim();
if (title) {
const task = {
id: state.nextId++,
title: title,
isCompleted: false,
};
state.tasks.push(task);
}
},
toggleTask({state}, id) {
const task = state.tasks.find((t) => t.id === id);
task.isCompleted = !task.isCompleted;
},
deleteTask({state}, id) {
const index = state.tasks.findIndex((t) => t.id === id);
state.tasks.splice(index, 1);
},
}; const initialState = {
nextId: 1,
tasks: [],
}; // -------------------------------------------------------------------------
// Task Component 可点击任务标题来切换复选框状态:
    // -------------------------------------------------------------------------
const TASK_TEMPLATE = xml/* xml */`
<div class="task" t-att-class="props.task.isCompleted ? 'done' : ''">
<input type="checkbox" t-att-checked="props.task.isCompleted"
t-att-id="props.task.id"
t-on-click="dispatch('toggleTask', props.task.id)"/>
<label t-att-for="props.task.id"><t t-esc="props.task.title"/></label>
<span class="delete" t-on-click="dispatch('deleteTask', props.task.id)"></span>
</div>`; class Task extends Component {
static template = TASK_TEMPLATE;
static props = ["task"];
dispatch = useDispatch();
} // -------------------------------------------------------------------------
// App Component
// -------------------------------------------------------------------------
const APP_TEMPLATE = xml/* xml */`
<div class="todo-app">
<input placeholder="Enter a new task" t-on-keyup="addTask" t-ref="add-input"/>
<div class="task-list">
<Task t-foreach="displayedTasks" t-as="task" t-key="task.id" task="task"/>
</div>
<div class="task-panel" t-if="tasks.length">
<div class="task-counter">
<t t-esc="displayedTasks.length"/>
<t t-if="displayedTasks.length lt tasks.length">
/ <t t-esc="tasks.length"/>
</t>
task(s)
</div>
<div>
<span t-foreach="['all', 'active', 'completed']"
t-as="f" t-key="f"
t-att-class="{active: filter.value===f}"
t-on-click="setFilter(f)"
t-esc="f"/>
</div>
</div>
</div>`; class App extends Component {
static template = APP_TEMPLATE;
static components = {Task}; inputRef = useRef("add-input");
tasks = useStore((state) => state.tasks);
filter = useState({value: "all"});
dispatch = useDispatch(); mounted() {
this.inputRef.el.focus();
} addTask(ev) {
// 13 is keycode for ENTER
if (ev.keyCode === 13) {
this.dispatch("addTask", ev.target.value);
ev.target.value = "";
}
} get displayedTasks() {
switch (this.filter.value) {
case "active":
return this.tasks.filter((t) => !t.isCompleted);
case "completed":
return this.tasks.filter((t) => t.isCompleted);
case "all":
return this.tasks;
}
} setFilter(filter) {
this.filter.value = filter;
}
} // -------------------------------------------------------------------------
// Setup code
// -------------------------------------------------------------------------
function makeStore() {
const localState = window.localStorage.getItem("todoapp");
const state = localState ? JSON.parse(localState) : initialState;
const store = new Store({state, actions});
store.on("update", null, () => {
localStorage.setItem("todoapp", JSON.stringify(store.state));
});
return store;
} function setup() {
owl.config.mode = "dev";
App.env.store = makeStore();
const app = new App();
app.mount(document.body);
} whenReady(setup);
})();
.todo-app {
width: 300px;
margin: 50px auto;
background: aliceblue;
padding: 10px;
} .todo-app > input {
display: block;
margin: auto;
} .task-list {
margin-top: 8px;
} .task {
font-size: 18px;
color: #111111;
display: grid;
grid-template-columns: 30px auto 30px;
}

//在用户鼠标悬浮到任务上方时添加视觉反馈:
.task:hover {
background-color: #def0ff;
} .task > input {
margin: auto;
} .delete {
opacity: 0;
cursor: pointer;
text-align: center;
} .task:hover .delete {
opacity: 1;
} .task.done {
opacity: 0.7;
}

//对已完成任务的标题添加中划线
.task.done label {
text-decoration: line-through;
} .task-panel {
color: #0088ff;
margin-top: 8px;
font-size: 14px;
display: flex;
} .task-panel .task-counter {
flex-grow: 1;
} .task-panel span {
padding: 5px;
cursor: pointer;
} .task-panel span.active {
font-weight: bold;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>OWL Todo App</title>
<link rel="stylesheet" href="app.css" />
<script src="owl.js"></script>
<script src="app.js"></script>
</head>
<body></body>
</html>

owl.js  在   https://github.com/odoo/owl

 

最新文章

  1. Python 常用模块之time&amp;datetime 和random
  2. 学习AOP之JAVA的代理机制
  3. 004_kafka_安装运行
  4. 【学习/研发】嵌入式Linux/Android开发有它就够了——迅为4412开发板
  5. 最长回文子串(Manacher算法)
  6. Go 语言开发的基于 Linux 虚拟服务器的负载平衡平台 Seesaw
  7. 重力加速度陀螺仪传感器MPU-6050(一)
  8. iOS仿喜马拉雅FM做的毕业设计及总结(含新手福利源码)
  9. UVA - 10131Is Bigger Smarter?(DAG上的DP)
  10. R语言 关联规则
  11. 【BZOJ3277】串(后缀自动机)
  12. luoguP1919 A*B Problem升级版 ntt
  13. Nginx tcp限制并发、IP、记日志
  14. [译]SQL SERVER 2016 – Temporal Tables
  15. php爬虫最最最最简单教程
  16. Python学习笔记第二十二周(前端知识点补充)
  17. html调用静态json例子
  18. Linux命令-文件处理命令:cat
  19. 20145312 实验二《 Java面向对象程序设计》
  20. python开发_python中的range()函数

热门文章

  1. 【NX二次开发】Block UI 超级截面
  2. 【NX二次开发】Block UI 集列表
  3. itools安装程序无法创建临时文件夹
  4. 『动善时』JMeter基础 — 46、使用Badboy工具录制JMeter脚本
  5. Lc_704二分查找
  6. 一、RabbitMQ 概念详解和应用
  7. uniapp 微信小程序 生成二维码
  8. ACdream 1007 a+b 快速幂 java秒啊,快速幂 避免 负数移位出错
  9. C. Learning Languages 求联通块的个数
  10. nginx限流模块(防范DDOS攻击)