
本文解析 Odoo 12 中无法运行 Odoo 14 标准 JS 小部件代码的根本原因——web.public.widget 在 Odoo 12 中尚未引入,需降级适配为 website.snippet.editor 或 core.Widget 并调整生命周期方法。
本文解析 odoo 12 中无法运行 odoo 14 标准 js 小部件代码的根本原因——`web.public.widget` 在 odoo 12 中尚未引入,需降级适配为 `website.snippet.editor` 或 `core.widget` 并调整生命周期方法。
在 Odoo 14 中,前端 JavaScript 扩展广泛采用 web.public.widget 作为公共网站组件的基类,它提供了标准化的 DOM 选择器绑定、事件委托、异步初始化(start())等能力。然而,该模块直到 Odoo 13.0 才正式引入,Odoo 12.0 的前端架构中并不存在 web.public.widget —— 这正是您提供的代码在 Odoo 12 环境下报错(如 Cannot read property 'extend' of undefined)的直接原因。
要使相同功能在 Odoo 12 中正常工作,必须进行以下关键改造:
✅ 1. 替换基类:从 web.public.widget 降级为 core.Widget
Odoo 12 支持 web.core 模块中的通用 Widget 类,它是所有前端组件的原始基类,具备 start()、事件绑定(this.$el.on(...))等基础能力:
odoo.define('product_dimensions.website_sale', function (require) {
"use strict";
var core = require('web.core');
var _t = core._t;
var ajax = require('web.ajax');
var Widget = core.Widget; // ✅ Odoo 12 兼容基类
var ProductDimensions = Widget.extend({
// 注意:Odoo 12 不支持 selector + 自动绑定,需手动触发初始化
start: function () {
var self = this;
// 显式绑定到目标容器(如 .oe_website_sale)
this.$el = $(this.el).find('.oe_website_sale');
if (!this.$el.length) return;
this.product_id = this.$el.find('#product_id').val();
// ✅ 手动绑定事件(替代 events: {...} 声明式语法)
this.$el.on('change', 'input[name="wide"]', function () {
self._onWidthChange();
});
this.$el.on('change', 'input[name="high"]', function () {
self._onHeightChange();
});
return this._super.apply(this, arguments);
},
_onWidthChange: function () {
var wide = parseFloat($('input[name="wide"]').val());
console.log(this.product_id);
ajax.jsonRpc("/shop/product/min_dimensions", 'call', {'product_id': this.product_id}).then(function (data) {
if (wide < data.wide_mini) {
alert(_t('The number you entered is less than the minimum width:') + data.wide_mini);
} else if (wide > data.wide_max) {
alert(_t('The number you entered is greater than the maximum width:') + data.wide_max);
}
});
},
_onHeightChange: function () {
var high = parseFloat($('input[name="high"]').val());
ajax.jsonRpc("/shop/product/min_dimensions", 'call', {'product_id': this.product_id}).then(function (data) {
if (high < data.high_mini) {
alert(_t('The number you entered is less than the minimum height:') + data.high_mini);
} else if (high > data.high_max) {
alert(_t('The number you entered is greater than the maximum height:') + data.high_max);
}
});
},
});
// ✅ 注册为全局小部件(Odoo 12 推荐方式)
core.action_registry.add('product_dimensions_website_sale', ProductDimensions);
return ProductDimensions;
});⚠️ 2. 关键注意事项
- 无自动 selector 匹配:Odoo 12 的 Widget 不支持 selector 属性自动查找并实例化 DOM 节点,必须在 start() 中显式定位(如 $(this.el).find(...))并手动绑定事件。
- 生命周期差异:start() 是唯一可靠的初始化钩子;避免依赖 init() 或 willStart()(后者在 Odoo 12 中未定义)。
- 模块依赖精简:移除 web.public.widget 依赖项,仅保留 web.core 和 web.ajax。
- 模板加载时机:确保该 JS 在页面 DOM 加载完毕后执行(建议通过 <script type="text/<a style=" color: text-decoration:underline title="javascript" href="https://www.php.cn/zt/15724.html" target="_blank">javascript"> 嵌入或在 assets_frontend 中正确继承)。</script>
? 总结
跨版本 JS 兼容的核心原则是「向后兼容、渐进降级」:Odoo 14 的 publicWidget 是对 Widget 的封装增强,而 Odoo 12 需回归基础 Widget 实现。只要规避高阶 API(如声明式 events、selector 自动挂载),改用手动 DOM 操作与事件绑定,即可在 Odoo 12 中完整复现尺寸校验逻辑。建议在 __manifest__.py 中明确指定 version 和 depends,并在开发环境严格按目标版本测试前端行为。
立即学习“Java免费学习笔记(深入)”;










