CSP 禁用 unsafe-inline 后 Vue 的 click 事件为啥不生效了?

诸葛雨泽 阅读 4

我在项目里加了 Content Security Policy,去掉了 ‘unsafe-inline’,结果页面上所有 @click 绑定的事件都失效了,控制台报错说被 CSP 阻止。但我不明白为啥 Vue 的事件也算 inline?

我试过把事件逻辑移到 methods 里,还是不行。是不是因为 Vue 在编译时生成了内联 handler?下面是最简复现代码:

<template>
  <button @click="handleClick">点我</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      alert('clicked');
    }
  }
}
</script>
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
闲人芯依
Vue 编译 @click 时会生成内联的 onclick 属性,这确实算是 inline 事件,所以被 CSP 拦了。

最简单的解决办法:在 CSP 里用 nonce 放行。

服务器端(以 Express 为例)生成个随机字符串:

// 服务器生成 nonce
const nonce = crypto.randomBytes(16).toString('hex');

// CSP 响应头
res.setHeader('Content-Security-Policy',
script-src 'nonce-${nonce}' 'self'; style-src 'nonce-${nonce}' 'self';
);

// 模板中注入 nonce
res.render('index', { nonce });


index.html 模板里给 script 标签加 nonce 属性:





...







Vue 3 需要在创建 app 时配置:

const app = createApp(App);
app.config.compilerOptions = {
// 生成内联事件处理器时带上 nonce
onRenderTracked: () => {}, // 这行其实不需要
};
// Vue 3.2+ 用这个
app.config.optionMergeStrategies.nonce = (parent, child) => child;


实际上 Vue 3 在启用 CSP 时会自动尝试从当前 script 标签读取 nonce。

如果上面这些嫌麻烦,还有个野路子:不用 @click,改为在 mounted 里用 addEventListener 绑定事件,这样就不是 inline handler 了。
点赞
2026-03-13 15:26