首页 > 解决方案 > Vue 将任何标签中的“open”属性替换为“open”值

问题描述

我在 laravel 刀片模板中使用 vue.js (v2.6.12) 组件。对于该项目,我还使用了 MathML,其中我需要使用 tag 的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属性就会转换为 this 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 应用程序初始化。


这里的问题是:

  1. 为什么 vue 会这样改变 open 属性?
  2. 我怎样才能停止这种行为,到 vue 应用程序区域内的整个页面,或者至少在我选择的地方(比如 using v-pre),是否有 ary config 或任何其他方式?

标签: vue.jsvuejs2attributesmathml

解决方案


为什么

在 HTML 规范中有一些属性称为布尔属性。规范规定了此类属性的值:

如果该属性存在,则其值必须是空字符串或与属性的规范名称匹配的不区分大小写的 ASCII 值,并且没有前导或尾随空格。

布尔属性不允许使用值“true”和“false”。要表示假值,必须完全省略该属性。

open是布尔属性之一 - 它是为<details> 元素定义的

Vue 2 的问题在于,它将大多数布尔属性视为全局属性——而不考虑它所在的元素。结果是open属性总是以值“open”呈现,或者如果值是假的(当v-binding 时)被删除。如第二个示例所示,这已在 Vue 3 中修复...

如何

使用v-pre是要走的路,但不幸的是你有一个错误。
看到这个问题此提交(2020 年 9 月 21 日)已经修复了该错误,但尚未发布...

  1. 示例 - “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>

  2. 示例 - 它在 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>


推荐阅读