其他分享
首页 > 其他分享> > 发现一odoo学习好资料

发现一odoo学习好资料

作者:互联网

第一章 OWL概述 · odoo技术开发白皮书

第一章 OWL简介

OWL是什么

OWL(Odoo Web Libary)是Odoo从14.0开始引入的前端框架, OWL区别于之前版本的QWeb技术, 与近些年来前端流行的框架(React, Vue, Angular, Backbone)更为相似. 如果你对现在的这些流行的前端框架有所了解,那么你一定明白这些框架的目的都在于简化之前那些由javascript来处理的琐碎的工作. 这些框架最大程度地解耦了你的HTML和Javascript代码, 动不动写几百行代码用来操作HTML DOM元素与监听事件的时代成为了过去式.

举个非常简单的例子,我们这里都有一段HTML代码:

<button id="countButton">Increment Count</button> 
 <button id="clearButton">Clear Count</button> 

 <div id="results">0</div>

这段代码定义了2个按钮,一个用来增加计数, 一个用来归零. 如果用我们过去的代码方式, 这段代码应该这么写:

// ew, gross 

 const clicks = 0; 

 const countButton = document.querySelector("#countButton"); 
 myButton.addEventListener("click", function() { 
     clicks += 1; 
     const results = document.querySelector("#results"); 
     results.innerHTML = clicks; 
 }); 

 const clearButton = document.querySelector("#clearButton"); 
 clearButton.addEventListener("click", function() { 
     clicks = 0; 
     const results = document.querySelector("#results"); 
     results.innerHTML = click; 
 });

这只是一小段代码, 随着项目量的增长, 这些代码的可读性将变得很差. 现在, 让我们来看一下现代框架们是如何处理的(OWL为例):

<button id="countButton" t-on-click="state.count++">Increment Count</button> 
 <button id="clearButton" t-on-click="state.count = 0">Clear Count</button> 

 <div id="results" t-esc="state.count"/>
 const { Component, useState } = owl; 

 class ClickComponent extends Component { 
     state = useState({ count: 0 }); 
 }

DOM操作和事件监听完全由框架来帮我们处理了, 代码变得非常简单.

Odoo为啥创建了OWL而没有使用React, Vue等既有框架?

哈, 这个可以看官方的回答

在笔者看来无非就两个原因, 一是现有框架不能完全满足Odoo的需求, 二是作为一个帮技术控,有足够的自信自己做一套出来, 同时也不想被其他框架制约.

主要特点

与旧框架相比,OWL香在以下几点, 写起来更简单, 更优雅, 可读性也更高.

生命周期的组件

在过去, 我们需要监控DOM的状态,以防止我们的代码运行时符合预期. 而现在, 我们知道我们的组件会在页面启动时加载, 在页面跳转时消亡, 而且我们有很多钩子用来处理这些事情, 而不再有$(document).ready了.

响应式虚拟DOM

如果你看了前面的代码, 那么你就看到了响应式绑定的好处, 我们只需要考虑如何组织处理数据, 而不用再关心如何操作处理DOM元素, 所有的DOM操作代码都被移除了,当我们的数据发生变化时, 页面自动进行了更新. 很多现代框架都提供了虚拟DOM用来跟踪前端结构发生的变化, 尤其是事件绑定的场景.

更好的可读性

移除了操作DOM的代码之后, 代码的可读性自然就提高了, 而且我们更容易把精力放到项目本身的逻辑处理中,对于编写测试脚本和测试用例来说显然也变得更容易.

开始学习

虽然OWL在15.0发布时又发生了变化, 但是我们的学习还是从14.0时开始, 下面的例子即基于odoo14.0, 后面我们会介绍15.0究竟与14.0有何不同.

我们依旧使用我们的书店模块, 这次主要工作在static/src/js目录中, 我们创建一个新文件夹components用来存放我们的组件代码.

OWL通过定义组件(Component)来渲染模板,加载数据, 加载子组件等工作. 在HTML中, 我们有header, div, span, textarea等标签来供我们使用, 当我们要创建一个OWL组件时,我们需要思考,当我们创建了这个组件,对我们的项目有什么好处.

本例子中,我们将创建一个组件用来显示销售单下的某个客户的订单历史信息.

创建和注册js类

我们在components文件夹下创建一个PartnerOrderSummary.js文件.

odoo.define("book_store.PartnerOrderSummary", function (require) {
    'use strict';

    const { Component } = owl;

    class PartnerOrderSummary extends Component {

    };

    Object.assign(PartnerOrderSummary,{
        template: "book_store.PartnerOrderSummary"
    });
});

跟14.0之前的版本一样, 所有的js文件都要在templates文件中注册到assets中:

<template id="assets_backend_book_store" inherit_id="web.assets_backend" name="book_store">
    <xpath expr="script[last()]" position="after">
        <script type="text/javascript" src="/book_store/static/src/js/component/PartnerOrderSummary.js"></script>
    </xpath>
</template>

为component创建模板

现在我们来为我们的组件创建一个模板文件(同样位于components文件夹内):

 <?xml version="1.0" encoding="UTF-8"?> 
 <templates xml:space="preserve"> 
     <t t-name="book_store.PartnerOrderSummary" owl="1"> 
         <div>My cool new widget</div> 
     </t> 
 </templates>

同样的,我们需要把模板文件放到QWeb中


"qweb":[
    "static/src/js/components/PartnerOrderSummary.xml"
],

在销售单中显示组件

现在我们需要把我们的组件显示到销售单中, 首先,我们需要更新我们的依赖:

 'depends': ['sale_management'],

重载表单的渲染方法挂载我们的组件

想要在销售单中显示我们的组件,最简单的办法就是重载表单的渲染方法, 下面我们将修改PartnerOrderSummary.js的文件内容:

odoo.define("book_store.PartnerOrderSummary", function (require) {
    'use strict';

    const FormRenderer = require("web.FormRenderer");
    const { Component } = owl;

    class PartnerOrderSummary extends Component {

    };

    Object.assign(PartnerOrderSummary, {
        template: "book_store.PartnerOrderSummary"
    });

    FormRenderer.include({
        async _render() {
            await this._super(...arguments);

            for (const element of this.el.querySelectorAll(".o_partner_order_summary")) {
                (new ComponentWrapper(this, PartnerOrderSummary))
                    .mount(element)
            }
        }
    });
});

如果你没有涉足过odoo的前端开发,那么这段代码来说阅读起来可能有点困难, 不过没关系, 我们只要知道通过ComponentWrapper, 我们可以在把要一个组件挂载到任何元素上.

(new ComponentWrapper(this, PartnerOrderSummary))
                    .mount(element)

添加div元素到销售单表单视图

从上面的代码中我们可以看到,要显示的组件需要定位到含有o_partner_order_summary样式的div标签上, 因此,接下来我们添加这个标签:

 <?xml version="1.0" encoding="utf-8"?> 
 <odoo> 
     <record id="sale_order_form_inherit" model="ir.ui.view"> 
         <field name="name">sale.order.form.inherit</field> 
         <field name="model">sale.order</field> 
         <field name="inherit_id" ref="sale.view_order_form"/> 
         <field name="arch" type="xml"> 
             <field name="payment_term_id" position="after"> 
                 <div class="o_partner_order_summary" colspan="2"/> 
             </field> 
         </field> 
     </record> 
 </odoo>

然后把我们的视图文件放到_mainfest_.py文件中:

 'data': [
        'security/ir.model.access.csv',
        'views/views.xml',
        "views/sale.xml"
 ]

标签:OWL,const,PartnerOrderSummary,代码,odoo,学习,资料,组件,我们
来源: https://blog.csdn.net/fqfq123456/article/details/123186632