为什么我的 require.js 配置中的 shim 的 `init` 没有被调用?
Why `init` of shim in my require.js configuration not called?
更新:
我在 backbone 中编写了一个小模块来处理这个 csrf 令牌问题,直到我收到@Louis 回答的推送通知。
他的回答非常优雅而且看起来不错,但我会把 a link 留给我的 backbone.csrf 模块 github 回购只是为了任何需要它的人。
============================================= =======================
我正在使用 Backbone 作为我的前端框架以及我的 Django 后端。
为了与 Django 的 CSRF 保护系统兼容,我必须配置我的 Backbone.sync
以在发送前为每个 AJAX 请求设置 CSRF 请求 header。
由于我使用 require.js 进行模块化 javascript 开发,所以我尝试在 require.config
的 shim.init
中进行配置这样一旦 Backbone 在浏览器上加载,就会触发此覆盖:
<script>
var require = {
...
shim: {
'jquery': {'exports': 'jQuery'},
'backbone': {
'deps': ['underscore', 'jquery'],
'exports': 'Backbone',
'init': function(_, $) {
alert('NOT EVEN CALLED');
var originalSync = this.Backbone.sync;
this.Backbone.sync = function(method, model, options) {
options.beforeSend = function(xhr) {
xhr.setRequestHeader('X-CSRFToken', window.csrf_token);
}
return originalSync(method, model, options);
}
}
}
}
}
</script>
// Load require.js
<script src="require.js"></script>
虽然Backbone已经加载成功,但是require配置的'init'没有被调用
有什么问题?
查看 annotated source,我看到 Backbone 在检测到它是 运行 AMD 加载程序时调用 define
。将 shim
与调用 define
的模块一起使用会导致未定义的行为,因为 shim
适用于 不调用 define
的模块。
您可以使用像这样的假 backbone
模块实现您想要的,您将其保存在名为 backbone-glue.js
:
的文件中
define(['backbone'], function (Backbone) {
var originalSync = Backbone.sync;
Backbone.sync = function(method, model, options) {
options.beforeSend = function(xhr) {
xhr.setRequestHeader('X-CSRFToken', window.csrf_token);
}
return originalSync(method, model, options);
};
return Backbone;
});
然后在 RequireJS 的配置中应该有这样的映射:
map: {
'*': {
backbone: 'backbone-glue'
},
'backbone-glue': {
backbone: 'backbone'
}
}
这样做的目的是,当需要模块 backbone
时,RequireJS 在任何地方 (*
) 加载 backbone-glue
。但是,在 backbone-glue
中,当需要 backbone
时,则加载 backbone
。这允许 backbone-glue
加载原始 Backbone。
更新:
我在 backbone 中编写了一个小模块来处理这个 csrf 令牌问题,直到我收到@Louis 回答的推送通知。
他的回答非常优雅而且看起来不错,但我会把 a link 留给我的 backbone.csrf 模块 github 回购只是为了任何需要它的人。
============================================= =======================
我正在使用 Backbone 作为我的前端框架以及我的 Django 后端。
为了与 Django 的 CSRF 保护系统兼容,我必须配置我的 Backbone.sync
以在发送前为每个 AJAX 请求设置 CSRF 请求 header。
由于我使用 require.js 进行模块化 javascript 开发,所以我尝试在 require.config
的 shim.init
中进行配置这样一旦 Backbone 在浏览器上加载,就会触发此覆盖:
<script>
var require = {
...
shim: {
'jquery': {'exports': 'jQuery'},
'backbone': {
'deps': ['underscore', 'jquery'],
'exports': 'Backbone',
'init': function(_, $) {
alert('NOT EVEN CALLED');
var originalSync = this.Backbone.sync;
this.Backbone.sync = function(method, model, options) {
options.beforeSend = function(xhr) {
xhr.setRequestHeader('X-CSRFToken', window.csrf_token);
}
return originalSync(method, model, options);
}
}
}
}
}
</script>
// Load require.js
<script src="require.js"></script>
虽然Backbone已经加载成功,但是require配置的'init'没有被调用
有什么问题?
查看 annotated source,我看到 Backbone 在检测到它是 运行 AMD 加载程序时调用 define
。将 shim
与调用 define
的模块一起使用会导致未定义的行为,因为 shim
适用于 不调用 define
的模块。
您可以使用像这样的假 backbone
模块实现您想要的,您将其保存在名为 backbone-glue.js
:
define(['backbone'], function (Backbone) {
var originalSync = Backbone.sync;
Backbone.sync = function(method, model, options) {
options.beforeSend = function(xhr) {
xhr.setRequestHeader('X-CSRFToken', window.csrf_token);
}
return originalSync(method, model, options);
};
return Backbone;
});
然后在 RequireJS 的配置中应该有这样的映射:
map: {
'*': {
backbone: 'backbone-glue'
},
'backbone-glue': {
backbone: 'backbone'
}
}
这样做的目的是,当需要模块 backbone
时,RequireJS 在任何地方 (*
) 加载 backbone-glue
。但是,在 backbone-glue
中,当需要 backbone
时,则加载 backbone
。这允许 backbone-glue
加载原始 Backbone。