我在 Vue 组件中有一个名为 src
的 Prop ,它像这样绑定(bind)到 :style
:
<template>
<section :class="color" class="hero" :style="{ backgroundImage: src && 'url(' + src + ')' }">
<slot></slot>
</section>
</template>
<script>
export default {
props: ['src', 'color']
}
</script>
我想做的是创建一个响应式 Prop 列表,根据网站访问者的设备或屏幕大小使用这些 Prop 。
例如,我想象一个 Prop 列表,如 src-sm
、src-md
、src-lg
等。用户将为不同的设备尺寸输入不同的图像 url,样式属性将根据屏幕/尺寸使用适当的 url。
这在 VueJS 中可能吗?如果是这样,知道怎么做吗?
谢谢。
最佳答案
不幸的是,您尝试做的事情并非微不足道。这是因为内联样式标签不能接受媒体查询。
spec声明:
The value of the style attribute must match the syntax of the contents of a CSS declaration block
解决方案 1: 此解决方案是最简单的,也许并不完全是您正在寻找的解决方案。
它的工作原理是包含 img
元素,并通过 CSS 显示和隐藏它们。
<template>
<div>
<img class="image--sm" :src="src.sm" />
<img class="image--md" :src="src.md" />
<img class="image--lg" :src="src.lg" />
</div>
</template>
<script>
export default {
props: {
src: Object
}
}
</script>
<style>
.image--md,
.image--lg {
display: none;
}
@media (min-width: 400px) {
.image--sm {
display: none;
}
.image--md {
display: block;
}
}
@media (min-width: 600px) {
.image--md {
display: none;
}
.image--lg {
display: block;
}
}
</style>
Example: https://jsfiddle.net/h3c5og08/1/
解决方案 2:
图像标记可能不是您要达到的预期效果。此解决方案在头部创建样式标签并注入(inject) css 内容以更改背景图像。
Vue 模板中不能有样式标签。它会抛出如下错误:
Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as , as they will not be parsed.
正如错误描述的那样,vue 被设计为 UI 的 map 状态。禁止在模板中使用 style
标签,因为这可能会导致泄漏到外部世界。
虽然您不能在模板中声明样式,但我们可以在组件的挂载钩子(Hook)中使用一些 JS 来添加目标样式和动态样式。
首先,我们需要将动态样式限制到该元素。我们可以使用创建的组件的内部 id this._uid
,附加到 css 的范围。 (请注意,这是内部 API,因此可能会发生变化)
<template>
<div class="image" :data-style-scope="_uid">
</div>
</template>
下一部分是在计算属性中生成样式,稍后注入(inject)到样式 block 中。您可以扩展此计算属性,以有条件地分配属性等。注意:仅将属性保留为动态值。
css () {
const selector = `.image[data-style-scope="${this._uid}"]`
const img = val => `${selector} { background-image: url("${val}"); }`
const sm = img(this.sm)
const md = img(this.md)
const lg = img(this.lg)
return `
${sm}
@media (min-width: 200px) { ${md} }
@media (min-width: 300px) { ${lg} }
`
}
这个从 css
计算属性生成的字符串是我们现在在 mount 上创建样式标签时将使用的字符串。在 mount 我们创建一个样式节点并附加到头部。将节点分配给 vm 以供引用。
使用 vm 中的引用,我们可以观察对计算更新样式节点的更改。
记得在销毁组件之前进行清理,删除样式节点。
{
data () {
return {
// Reference data properties
style: null,
styleRef: null
}
},
mounted () {
// Create style node
let style = document.createElement('style')
style.type = "text/css"
style.appendChild(document.createTextNode(''))
// Assign references on vm
this.styleRef = style
this.style = style.childNodes[0]
// Assign css the the style node
this.style.textContent = this.css
// Append to the head
document.head.appendChild(style)
},
beforeDestroy () {
// Remove the style node from the head
this.style.parentElement.removeChild(this.style)
},
computed: {
css () {
// ...
}
},
watch: {
css (value) {
// On css value change update style content
this.style.textContent = this.css
}
}
}
Working Example: https://jsfiddle.net/bLkc51Lz/4/
关于css - Vue 组件中的响应式 Prop ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46043884/