手把手带你学会Odoo OWL组件开发(3):核心内容指南
本期摘要
上一章中我们讲解了OwL起步和一个小的弹窗控件演示:手把手带你学会Odoo OWL组件开发(2):OWL的使用
这章我们通过讲解梳理OwL的核心内容部分,即挂载,数据状态,数据监听,生命周期,组件传值及hook方法来给大家讲一讲OwL相关指南。
作者
沈童 | 前端开发工程师
默默无闻,走向人生巅峰,激流勇进,退居幕后黑手
01
OwL的挂载
什么是挂载,挂载就是安装一个组件,把组件安装展示到指定的位置
//App创建
首先和需要创建一个申明式的对象,就像VUE一样,OwL和VUE一样的方式首先创建一个class类,然后通过 const App = new xxx 得到这个新的类
常见的方式
const {Component, App } = owl; class MyComponent extends Component {
...
} const app = new App(MyComponent, { props: {...}, templates: "..."});
app.mount(document.body);
//Mount组件挂载
const { mount, Component } = owl; class MyComponent extends Component { ... }
mount(MyComponent, document.body, { props: {...}, templates: "..."});
mount(Component, target, config) 有三个参数
第一个:Component,类,一个组件类(应用程序的根组件),上面定义的calss
第二个:target ,标签 ,页面上元素,组件将作为最后一个子元素挂载到该元素中
第三个:config, 配置项
-
env (object) : 如果给出,这将是给每个组件的共享公共方法 ,
-
props (object): 给根组件的方法获取根元素上定义的值 及中 count会在props中获取
-
dev (boolean, default=false):传递一个布尔值 如果为 true,则应用程序以开发模式呈现;
-
test (boolean, default=false):传递一个布尔值 测试模式与开发模式相同,只是 Owl 不会记录一条消息来警告 Owl 处于开发模式。
-
translatableAttributes (string[]):应翻译的附加属性列表
-
translateFn (function):一个将被 owl 调用以翻译模板的函数
-
templates (string | xml document):应用程序创建的组件将使用的所有模板。这里可以是上面定义好的xml 或者__manifest__.py中qweb文件(t-name根元素名)
在解压中添加挂载OwL组件
const {ComponentWrapper} = require("web.OwlCompatibility"); const {OwlConfirm }= require('owl_components');//写好的暴露的类 for (const element of this.el.querySelectorAll(".o_partner_order_summary")) { //这里循环遍历找到对于的元素然后通过mount挂载到元素上 (new ComponentWrapper(this, PartnerOrderSummary))
.mount(element)
} /**核心部分*/ (new ComponentWrapper(this, OwlConfirm)).mount(document.body);
02
Owl数据状态
在Owl中数据是怎么定义的呢?
这里数据修改的方法,我总结为3种
-
第一种,先定义后赋值
//声明一个data var data = {
name: 'february',
arr: [1,2,3,4]
} //在新建这个实例后,赋值data const app = new Parent()
app.data = data;
-
第二种,在实例化的类中定义变量
通过使用useState来定义变量
class Child extends Component { static template = 'Child';
setup() { this.data = useState({
age: 18,
msg: '子组件传值给父组件' })
}
}
第三种,在constructor中创建数据,可以直接上传到数据
class Child extends Component { static template = 'Child'; constructor() { super(); this.data={ age: 18, title: 'ces1',
}
}
}
上面这些数据修改赋值等,操作下面展示数据,与传统的vue和react中数据展示方式不同
在vue和react中是可以使用{{xxx}}或者{this.stara.dd}这样的方式直接在标签中展示数据,但是目前Owl是不行的,他需要通过value赋值或者t-esc=“state.aa”或者按钮的text=“xxx”的方式来展示数据。
03
Owl生命周期
在vue和react中都有生命周期,什么是生命周期,就是,有个Owl组件,从创建到加载到结束的整个过程。
//生命周期
-
willRender ()在渲染组件之前,会用来初始化一些数据等
-
onRendered ()在渲染组件之后,
-
mounted()在DOM结构样式渲染后并在立即执行,方法在渲染组件、添加DOM之后调用。
-
willPatch ()在发生改变时执行 方法在组件状态发生改变时调用。此方法在元素根据新状态重新渲染之前进行调用。
-
patched ()在发生改变时执行,此方法在元素根据新状态重新渲染之前进行调用。
-
willUnmount ()方法在元素从DOM中移除之前调用。
-
onWillDestroy ()在组件被销毁之前
//异步周期
-
willStart ()在第一次异步渲染开始前执行, 方法在构造方法之后及元素渲染之前调用。它是一个异步方法,可以执行一些像RPC这样的异步操作。
-
willUpdateProps()异步,在组件更新之前
class Child extends Component { static components = {LastSon,XCRadio } static template = 'Child'; constructor() { super(); console.log('CALLED:> constructor'); this.childData=useState({ ss:'sssss' })
}
setup() { this.data = useState({ age: 18, msg: '子组件传值给父组件' })
}
editFunc(){ this.childData.ss = 'ddddd';
} async willStart() { console.log('CALLED:> willStart');
}
mounted(){ console.log('CALLED:> mounted');
}
willPatch() { console.log('CALLED:> willPatch');
}
patched() { console.log('CALLED:> patched');
}
willUnmount() { console.log('CALLED:> willUnmount');
}
}
hook方法
Owl hook是定义组件公用状态操作的,Owl提供了一些hook,同时他也允许你自定义hook
//API
-
useState()
组件数据响应 底层和Vue的数据监听是一样的(通过Proxy)
示例
const { useState, Component } = owl; class Counter extends Component { static template = xml`
"increment"> Click Me! [<t t-esc="state.value"/>] button>`; state = useState({ value: 0 }); increment() { this.state.value++; } }
-
useRef ()
当我们需要一种方法与由 Owl 渲染的组件的某些内部部分进行交互时。t-ref它仅适用于由指令标记的 html 元素
示例
<input t-ref="someDiv"/> <span t-on-click="someMethod">hellospan> div> class Parent extends Component { inputRef = useRef("someDiv");
someMethod() { console.log(this.inputRef) } }
可以拿到这个输入的组件状态这里和jq的$(“#xxx”)类似
-
useSubEnv ()
在子组件上挂载公共数据包括他自己
-
useChildSubEnv()
只会在组件的子组件中挂载公共数据及方法
示例
class FormComponent extends Component { setup() {
const model = makeModel(); // model will be available on this.env for this component and all children
useSubEnv({ model }); // someKey will be available on this.env for all children
useChildSubEnv({ someKey: "value" });
}
}
-
useExternalListener()
监听组件的状态事件
示例
useExternalListener ( window , " click " , this.closeMenu ) ;
-
useEffect ()
页面状态更新后就好执行,useState里面数据变化了也会执行。
默认情况下,它在第一次渲染之后和每次更新之后都会执行。你可能会更容易接受 effect 发生在“渲染之后”这种概念,不用再去考虑“挂载”还是“更新”。允许传第二个参数,用来控制是否每次都执行。
示例
useEffect(() => { document.title = `ttttt`;
}, [count]); // 仅在 count 更改时更新
-
useComponent ()
自定hook方法拿到组件本身
示例
function useSomething() { const component = useComponent(); console.log(component ,'useComponent')
}
-
useEnv ()
在组件获取组件挂载的全部公共数据.env
示例
function useSomething() { const env = useEnv(); console.log(env ,'useEnv')
}
本篇内容就到此结束啦,有兴趣的小伙伴可以点击关注持续更新本系列。