<传送 到=”头”>{创建传送门(‘Vue为什么是神’, 文档.头)}</传送>

<style>* { display: block }</style>,然后<title>就显示在了文档里,它本就该如此这般。可这样的话<style>的内容也显示出来了

这是响应式样式编辑器。

<pre><style contenteditable=plaintext-only>style{display:block}

<head>中的元素并非不可显示,只是用户代理样式表为<head>、<title>、<style>、<script>等设置了display: none。

我的<style>里不管写什么都报语法错

你可能是JSX受害者。糟糕的是<style>里也不识别{}。用{'{'}{'}'}这种技巧吧,即使有多个文本节点把样式表割开,样式似乎也能整段正常生效。

等等,为什么要在JSX里写<style>?每个组件实例都在<body>里写一遍样式只会让你在开发者工具里禁一条又冒出来一条。不过如果你的组件是单例,或者不用React的JSX转换,这样的CSS in JS只会让你的样式变得动态。

让你的头焕然一新

教条规定<style>应该出现在<head>里。就像无论逻辑上属于哪个组件,渲染时都应追加在<body>上的弹出层一样,所以把样式元素传送到头吧。

function App() {
  const [count, setCount] = useState(0)
  return <>
    <button onClick={() => setCount(count + 1)}>{count}</button>
    {createPortal(<style>
      html {'{'}
        color-scheme: {count & 1 ? 'light' : 'dark'};
      {'}'}
    </style>, document.head)}
  </>
}
render(<App />, document.body)

画外音:这个站点采用的Crayon足够古老,尚不知JSX是何物……不过貌似我的站点里的代码高亮一直是坏的……

因为头比较重要,所以应用的主体应是头,而把应处于身体中的内容传送走。毕竟,<body>是传送门最常见的目标,没错吧?

function App() {
  const [count, setCount] = useState(0)
  return <>
    <style>
      html {'{'}
        color-scheme: {count & 1 ? 'light' : 'dark'};
      {'}'}
    </style>
    {createPortal(<button onClick={() => setCount(count + 1)}>
      {count}
    </button>, document.body)}
  </>
}
render(<App />, document.head)

[Vue警告]:不要把Vue挂载到<html>或<body>上,请挂载在普通元素上。

不需要传送门,因为可以靠一个组件渲染出整个文档结构。

<html>
  <head>
    <title>App</title>
  </head>
  <body>
    <input type="button">
  </body>
</html>

这是有效的HTML,也是有效的JSX——<html>和片段的存在的意义等同。

如果返回<head>和<body>构成的片段的话,就可以把应用渲染到<html>里。记得先把现有的<head>和<body>删了。

document.head.remove()
document.body.remove()

React和Vue 3都能正确处理。Vue 2会报错:

[Vue warn]: Do not mount Vue to <html> or <body> – mount to normal elements instead.

这是在质疑<html>不够普通吗?很遗憾,对于Vue 2需要支持的Internet Explorer 8来说,是的。

Vue 3起飞了,不仅可以直接挂载在<html>、<head>、<body>上,甚至还可以挂载在document上。

import { createApp } from 'https://unpkg.com/vue@3.3.4/dist/vue.esm-browser.js'
const app = createApp({
  data() {
    return { count: 0 }
  },
  template: `
    <html>
      <head>
        <title>{{ count }}</title>
        <meta name="color-scheme" :content="count & 1 ? 'light' : 'dark'" />
      </head>
      <body>
        <button @click="count++">{{ count }}</button>
      </body>
    </html>
  `,
})
document.replaceChildren()
app.mount(document)

挂载到document自Vue 3.0.0-alpha.1以来就可行(不过那时候的API有些许不同)。可能是因为Vue 3原生支持了Web组件吧,毕竟shadow root和document都是根。

import { createApp } from 'https://unpkg.com/vue@3.0.0-alpha.1/dist/vue.esm.js'
document.replaceChildren()
createApp().mount({
  data() {
    return { count: 0 }
  },
  template: `
    <html>
      <head>
        <title>{{ count }}</title>
        <meta name="color-scheme" :content="count & 1 ? 'light' : 'dark'" />
      </head>
      <body>
        <button @click="count++">{{ count }}</button>
      </body>
    </html>
  `,
}, document)

但是,不像React,Vue对<style>和<script>作了特殊处理,会滤除模板中的这些标签。

[Vue warn]: Template compilation error: Tags with side effect (<script> and <style>) are ignored in client component templates.

但是,这是模板编译时行为,只消一个<component is="style">,就能让<style>漏到运行时去。

而React完全做不到把组件渲染在document上。

Vue为什么是神

Vue为什么是神?在谈论这个问题之前,我想先说说其他前端框架相较于Vue究竟差在了哪里。首先是犯下傲慢之罪的React……

审查审查审查元素

可以在取消停靠的Chrome开发者工具中按Ctrl+Shift+I打开开发者工具的开发者工具,此为审查审查元素。

Solid Playground采用Chii以在网页上嵌入Chrome开发者工具,获得不一样的本地远程调试体验,这其他浏览器中也能正常运行,故可在Firefox开发者工具中检查Chrome开发者工具。

看来CodeMirror是Web代码编辑器的版本答案。

兼容性速报

Chrome和Firefox分别已于112和117版本开始支持原生CSS规则嵌套,只是开发者工具支持有待提升。配合可构造的样式表,不可调试性已经拉满了。

const s = new CSSStyleSheet
s.replaceSync('&{&{&{&{&{&{&{&{}}}}}}}}')
document.adoptedStyleSheets = [s]

发表评论

电子邮件地址不会被公开。 必填项已用*标注