Odoo Field Widget 入坑指南(四)

       今天,我们对odoo前端框架中的拖拽功能,进行详细讲解。

       首先,让我们来看一下本节内容的最终效果,如下图所示。可以看到,在面板中用户可以通过鼠标拖拽来对产品明细行进行排序。当鼠标点击目标明细行时,明细行将被选中。用户把选中的明细行移动至目标位置后,释放鼠标。鼠标释放的位置,就决定了明细行的最终排序。

       直观上看,这一过程非常简单,只是一个鼠标点击操作罢了。但是,在代码执行层面,此过程却异常复杂,涉及到多个函数。具体来讲,拖拽动作涉及以下几个过程:1)鼠标点击事件监听;2)鼠标选择对象定位;3)鼠标释放位置抓取。

        为了清晰地认识整个动态渲染过程,我们先从代码架构出发,对odoo前端涉及widget拖拽功能的代码进行讲解。如下图所示,odoo中用于实现拖拽功能的代码分为三个部分,它们分别是components,owl_tree_view 和 xml 。这些代码文件名的后缀,只有两种类型,分别是 .js (函数执行语句)和 .xml/.scss (模板样式语句)。也就是说,我们可以将这些代码归类为执行代码和模板代码,即JavaScript函数和xml/css样式代码。

       如此一来, 进一步观察。可以看到,它们中实现明细行渲染的代码只有 owl_tree_renderer.js 。其他代码均是辅助此渲染代码的配套函数或关联模板。因此,我们将从此 owl_tree_renderer.js 入手来展开讲解。

        代码层面,一个明细行的生成实则是由三步组成。第一步, owl_tree_renderer.js ,调用构建明细行的xml模板,即 owl_tree_view.xml 。第二步,owl_tree_view.xml 引用 components 组件,也就是 TreeItem.xml ,旨在完善明细行中的细节样式。第三步,HTML目标位置上,由JavaScript将前述两 xml 所生成的 HTML 元素添加至div中。

         那么,为何要将一段简单的HTML代码由两层嵌套结构模板来动态生成呢?其原因在于,JavaScript是以元素为单位来定位操作目标的。通过模块化、金字塔结构的代码实现,JavaScript可在调用模板时,以树状结构为基础,快速定位目标元素位置,以进行代码更新。

        另一方面,这些子代码的组成顺序、启用与否,也可以更改最终渲染结果的呈现样式。

        这一切,都为拖拽功能提供了重要的架构基础。

        在进一步讲解之前,让我们总结一下层级化模板的架构优势:1)层级化设计,有效减小了目标元素的索引时间;2)层级化设计允许样式变更仅与所在层有关,不涉及其他层代码,减少代码更新量;3)层级化设计对开发人员更加友好,允许开发团队分层施工,并行开发。

        接下来,我们将对代码展开来进行讲解。

       从渲染函数的起点入手,让我们展开 owl_tree_renderer.js 这一渲染器。

        可以看到,它其实也是一段结构化的代码。它最主要的功能是,告诉JavaScript需要使用哪一个模板来对目标元素进行渲染。本例中,代码中的 template 属性将目标模板指向了 owl_tutorial_views.OWLTreeRenderer这一模板。如此一来,当函数执行到 template 时,就会去调用xml中的OWLTreeRenderer 这个模板,来进行HTML渲染。

        接下来,我们来看一下此 template 的渲染效果。如上图所示,最终结果被分成了内层、外层两个样式块。而owl_tutorial_views.OWLTreeRenderer这一模板,仅仅能生成图中所示的外层样式块。

        也就是说,此xml 仅仅生成了用来包裹内层样式的 <div> 标签。

        而内层样式,则需要通过 components 中的 TreeItem.js 来进一步渲染。

        如图所示,内层样式是 owl_tree_view.xml 模板调用 TreeItem.xml 来进一步生成的。也就是说,最终的HTML页面样式是两次独立渲染的结果。任何一次渲染,都仅生成最终HTML中的一个部分。

        因此,用户拖拽动作触发动态更新时,可以只更新这两次渲染中的一个即可。

        如上图所示,截图中展示了一个归总的明细行。它其实就是一个正常的明细行,仅仅是显示的内容不同罢了。

        接下来,为实现递归式明细行展示,odoo 在明细行属性中增加了 child_id 和 parent_path 这两个属性。前端JavaScript 通过识别此二属性,即可判断当前明细行所在的位置与排序,以进行相应的位置安放。

         在了解完整个页面的 HTML代码后,最后一步就是让这些组件动起来

          在 odoo 中,为让组件能动起来,代码中需要增加四个函数,即 onDrageover(), onDragenter(), onDragleave(), onDrag() 。它们分别描述了鼠标在浏览器上的四种状态:鼠标悬浮,鼠标进入,鼠标离开,鼠标拖入。

        从代码层面来讲,拖拽动作,实际上可以分解为:

        1)鼠标点击时,将所在明细行编号存储至鼠标缓存中;

        2)鼠标释放时,所在位置明细行读取鼠标缓存中明细行编号;

        3)鼠标释放完成,页面更新排序顺序。

        整个过程的核心,一是每个明细行需要根据鼠标操作执行推送或存储编号操作,二是浏览器需要为鼠标建立单独存储变量,放置其所选内容编号。

       因此,为实现这一原理,接下来需要做的工作就是将以上所述功能用代码在 odoo 前端进行实现。具体实现方式,我们将在下一节中予以详细讲解。

       感谢大家的支持!

        

        

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值