css - Vue 组件中的响应式 Prop

标签 css vue.js vuejs2 vue-component

我在 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-smsrc-mdsrc-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/

相关文章:

vue.js - 无法访问输入事件的 keyCode/key 事件

css - 如何为 DIV 赋予几何形状?

html - 更改 WordPress 页面/帖子标记

javascript - 如何为每个单独的图像设置一个文本框?

vue.js - 如何从外部文件导入路由组件

javascript - 具有动态路由和组件的 Vue

php - 试图编辑一个 php 文件以将其内容放在一个 div 中

javascript - 如何使用vue.js/nuxt.js获取目录下的所有图片文件

javascript - VueJS - 在组件中呈现动态传递的模板

javascript - Vue.js 组件不显示组件方法中的数据