问题描述
我在 laravel 刀片模板中使用 vue.js (v2.6.12) 组件。
对于该项目,我还使用了 MathML,其中我需要使用 open
标记的 <mfenced>
属性设置为一些自定义值。以下是用 mathml 表示的数学示例。
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>f</mi>
<mfenced close="]" open="[">
<mrow><mi>a</mi><mo>,</mo><mi>b</mi></mrow>
</mfenced>
</math>
但是一旦页面呈现,open
属性就会转换为这个 open="open"
。我 100% 确定没有其他库或脚本被加载像这样更新,只是普通的 vue。这实际上打破了数学表达式。所以它看起来像这样:
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>f</mi>
<mfenced close="]" open="open">
<mrow><mi>a</mi><mo>,</mo><mi>b</mi></mrow>
</mfenced>
</math>
后来我意识到不仅在数学表达式中,任何标签,无论是 <div open="anything">...</div>
,<span open="anything">...</span>
,<custom-element open="something">...</custom-element>
具有 open
属性的行为都是一样的。即使我使用 v-pre
属性将其从 vue js 模板编译器中排除。
这不会发生,一旦我禁用了 vue 应用程序初始化。
这里的问题是:
解决方法
为什么
在 HTML 规范中有一些称为 boolean attributes 的属性。规范规定了此类属性的值可以是什么:
如果该属性存在,则其值必须是空字符串,或者是与该属性的规范名称不区分大小写的 ASCII 匹配值,且没有前导或尾随空格。
布尔属性不允许使用值“true”和“false”。要表示假值,必须完全省略该属性。
open
是布尔属性之一 - 它是为 <details>
element
Vue 2 的问题在于,它将大部分 boolean attributes 视为全局 - 没有考虑放置它的元素。结果是 open
属性总是以值“open”呈现,或者如果值为假(当 v-bind
ing 时)被移除。这在 Vue 3 中已修复,如第二个示例所示...
如何
使用 v-pre
是可行的方法,但不幸的是您有一个错误。
见this issue。该错误已通过此 commit(2020 年 9 月 21 日)修复,但尚未发布...
-
示例 - “With v-pre”应该适用于 Vue 版本 > 2.6.12
const vm = new Vue({ el: '#app',data() { return { message: 'Hi!',html: `<div open="[" close="]">Hi from html</div>` } },})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.12/vue.js"></script> <div id="app"> <div open="[" close="]">{{ message }}</div> <div v-html="html"></div> <div v-pre> <p open="[" close="]">With v-pre</p> </div> </div>
-
示例 - 它适用于 Vue 3 -
open
仅在放置在<details>
上时才被视为布尔属性const app = Vue.createApp({ data() { return { message: 'This works in Vue 3!',} },}) app.mount('#app')
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.11/vue.global.js" integrity="sha512-1gHWIGJfX0pBsPJHfyoAV4NiZ0wjjE1regXVSwglTejjna0/x/XG8tg+i3ZAsDtuci24LLxW8azhp1+VYE5daw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <div id="app"> <div open="[" close="]">{{ message }}</div> <details open="["> <summary>Details</summary> open attribute on details element is treated as boolean (renders empty value) </details> </div>
一种解决方法是创建一个设置属性的 directive(名为 "attr"
):
Vue.directive('attr',(el,binding) => el.setAttribute(binding.arg,binding.value || ''))
然后在您的模板中使用它,如 v-bind
,但与 v-attr
一起使用:
<mfenced v-attr:open="'['">
Vue.directive('attr',binding.value || ''))
new Vue({ el: '#app' })
<script src="https://unpkg.com/vue@2.6.12"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML"></script>
<div id="app">
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>f</mi>
<mfenced close="]" v-attr:open="'['">
<mrow><mi>a</mi><mo>,</mo><mi>b</mi></mrow>
</mfenced>
</math>
</div>