Odoo 中文社区

    • 注册
    • 登录
    • 搜索
    • 版块
    • 标签
    • 热门
    • 用户
    • 群组

    Odoo中文社区可以通过以下两个域名访问:shine-it.net , odoo.net.cn

    由于系统升迁的原因,本论坛部分较早期的内容存在格式和链接损坏失效的问题,并非本论坛系统本身的缺陷,望谅解

    本社区没有维护任何QQ群讨论组,任何与本社区同名的QQ群讨论组的言论与本社区无关!

    开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

    如果您登录系统碰到问题,请在微信公众号留言:

    [分享]OpenERP Web Client 事件处理源码初探

    Odoo 开发与实施交流
    9
    11
    10448
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • mrshelly
      mrshelly 最后由 编辑

      OpenERP Web Client 事件处理源码初探

      昨天(2013-09-22)在检查 sale.order  的 子表 sale.order.line product_id 中获取 context 传递丢失的问题时,
      需要了解一下 OpenERP 7.0 Web 模块的Javascript 源码.
      得群中 成都-gotham(30943392) 提示, 初略地了解了一下OpenERP 7.0 web 模块关于 客户端浏览器事件处理的一些
      设计. 仅供参考,望斧正...

      贴子不去分析 关于JS架构中 继承等技术. 只从应用程序切入点去分析.
      首先是首页

      <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $(function() {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var s = new openerp.init([&quot;web&quot;, &quot;web_kanban&quot;, &quot;web_diagram&quot;, &quot;web_graph&quot;, &quot;web_view_editor&quot;, &quot;web_calendar&quot;, &quot;base&quot;, &quot;web_tests&quot;, &quot;web_gantt&quot;]);<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var wc = new s.web.WebClient();wc.appendTo($(document.body));<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<br />
      



      var s = new openerp.init(....)  在 浏览器端做了 OpenERP 各模块的初始化载入工作.
      var wc = new s.web.WebClient();  这里就开始了 WebClient 的实例.
      我们重点就从 new 的这个 WebClient 入手.

      在 addons\web\static\static\src\js\chrome.js 代码中定义了 instance.web.WebClient
      同样, 不去纠结这个 Class 应该如何写.
      通常. 这类 Class 会以 init 实始化. start 方法开始.
      所以, 暂不去纠结为什么...
      直接看 WebClient.start() 的代码.

      <br />....<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!self.session.session_is_valid()) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.show_login();<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.show_application();<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />....<br />
      



      重点在这里..
      if 语句 判断了是否登陆.
      未登陆就执行 show_login 的登陆部分.
      否则就 show_application 显示整个客户端.

      show_login 部分, 咱们也暂时略过.

      show_application 部分

      <br />....<br />&nbsp; &nbsp; show_application: function() {<br />&nbsp; &nbsp; &nbsp; &nbsp; var self = this;<br />&nbsp; &nbsp; &nbsp; &nbsp; self.toggle_bars(true);<br />&nbsp; &nbsp; &nbsp; &nbsp; self.update_logo();<br />&nbsp; &nbsp; &nbsp; &nbsp; self.menu = new instance.web.Menu(self);<br />&nbsp; &nbsp; &nbsp; &nbsp; self.menu.replace(this.$el.find(&#039;.oe_menu_placeholder&#039;));<br />&nbsp; &nbsp; &nbsp; &nbsp; self.menu.on(&#039;menu_click&#039;, this, this.on_menu_action);<br />&nbsp; &nbsp; &nbsp; &nbsp; self.user_menu = new instance.web.UserMenu(self);<br />&nbsp; &nbsp; &nbsp; &nbsp; self.user_menu.replace(this.$el.find(&#039;.oe_user_menu_placeholder&#039;));<br />&nbsp; &nbsp; &nbsp; &nbsp; self.user_menu.on(&#039;user_logout&#039;, self, self.on_logout);<br />&nbsp; &nbsp; &nbsp; &nbsp; self.user_menu.do_update();<br />&nbsp; &nbsp; &nbsp; &nbsp; self.bind_hashchange();<br />&nbsp; &nbsp; &nbsp; &nbsp; self.set_title();<br />&nbsp; &nbsp; &nbsp; &nbsp; self.check_timezone();<br />&nbsp; &nbsp; },<br /><br />....<br />
      



      这部分代码 就初始化了菜单, 并显示了菜单. 显示完菜单的同时, bind_hashchange 中, 判断
      菜单是否完整载入. 菜单载入后

      <br />....<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.menu.has_been_loaded.done(function() {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var first_menu_id = self.menu.$el.find(&quot;a:first&quot;).data(&quot;menu&quot;);<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(first_menu_id) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.menu.menu_click(first_menu_id);<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<br />....<br />
      



                      var first_menu_id = self.menu.$el.find("a:first").data("menu");
      取出了 第一个菜单项, 并模拟点击. self.menu.menu_click(first_menu_id);

      重点就是这个 menu.menu_click 里了

      web.Menu.menu_click 中, 前面部分 是对于非末级菜单的处理..

      <br />....<br />&nbsp; &nbsp; &nbsp; &nbsp; if (action_id) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.trigger(&#039;menu_click&#039;, {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action_id: action_id,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; needaction: needaction,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id: id,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; previous_menu_id: this.current_menu // Here we don&#039;t know if action will fail (in which case we have to revert menu)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, $item);<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />....<br />
      


      如果该菜单项 上绑定了 action , 那么 就 this.trigger 一个 Menu 对象的 menu_click 事件.
      重点就在这里.
      trigger 的 menu_click 事件 是如何被捕捉到的呢? 按 成都-gotham(30943392) 提示. 在 web.WebClient.show_application 事件中:
      self.menu.on('menu_click', this, this.on_menu_action); 这里为 menu 注册了 menu_click 事件的处理方法 即 web.WebClient.on_menu_action

      在客户端打断点, 并测试成功.

      由此猜测. 在OpenERP 7.0 Web Client 的开发中. 可以在JS客户端对象中抛出 事件. 并在其他对象中注册对各种事件的捕获处理事件即可.

      如本例: 要对 菜单的点击中 去关联一个点击的事件处理.
      就在 Menu 对象中 注册 事件名. 并绑定一个 function 以及传递一个绑定该  function 的对象. 然后 其他地方只需要 trigger 该 对象的该方法即可
      (当然还可以传递很多参数)

      1 条回复 最后回复 回复 引用 0
      • wjfonhand
        wjfonhand 最后由 编辑

        不明觉厉

        GoodERP -- Odoo China fork

        1 条回复 最后回复 回复 引用 0
        • W
          wangpc 最后由 编辑

          总监威武,回头自己断点测试一下!

          1 条回复 最后回复 回复 引用 0
          • G
            gotham 最后由 编辑

            呵呵,也加入论坛了

            1 条回复 最后回复 回复 引用 0
            • C
              ccdos 最后由 编辑

              强帖留名

              1 条回复 最后回复 回复 引用 0
              • R
                rufeng1199 最后由 编辑

                好家伙,最近也在梳理 web 端逻辑,此文是 开端利器

                1 条回复 最后回复 回复 引用 0
                • ieitzyb
                  ieitzyb 最后由 编辑

                  “...context 传递丢失的问题...”,原来早有发现了

                  http://www.OuduPLM.com/ 苏州欧度软件,专注服装行业(鳴謝:37signals,Trello,ProcessON,重庆慧积,上海开阖)

                  1 条回复 最后回复 回复 引用 0
                  • P
                    panyi5202 最后由 编辑

                    这里面有几个问题:
                    [list type=decimal]
                    [li]同一个事件,能不能绑定多一个响应方法?后面的绑定会不会覆盖前面的绑定?[/li]
                    [li]如果可以同时绑定多个响应的话,这几个响应是并行还是串行?[/li]
                    [/list]

                    下次我也要找个机会试一下。

                    1 条回复 最后回复 回复 引用 0
                    • mrshelly
                      mrshelly 最后由 编辑

                      [quote author=panyi5202 link=topic=12397.msg28644#msg28644 date=1406772278]
                      这里面有几个问题:
                      [list type=decimal]
                      [li]同一个事件,能不能绑定多一个响应方法?后面的绑定会不会覆盖前面的绑定?[/li]
                      [li]如果可以同时绑定多个响应的话,这几个响应是并行还是串行?[/li]
                      [/list]

                      下次我也要找个机会试一下。
                      [/quote]

                      按OE 惯例. 应该是会都调用. 按 JS 的惯例 应该是并行....

                      1 条回复 最后回复 回复 引用 0
                      • A
                        alex1069010 最后由 编辑

                        正在学习oe,准备实施,翻个老帖。
                        可以绑定多个响应方法,不会覆盖。
                        JS不是多线程的,所以始终是串行,但是串行的顺序并不一定严格按照绑定顺序。

                        1 条回复 最后回复 回复 引用 0
                        • First post
                          Last post