【问题标题】:Vue.js dynamic <style> with variables带有变量的 Vue.js 动态 <style>
【发布时间】:2018-04-29 14:11:10
【问题描述】:

是否可以在style中添加动态变量?

我的意思是这样的:

<style>
    .class_name {
        background-image({{project.background}});
    }
    @media all and (-webkit-min-device-pixel-ratio : 1.5),
    all and (-o-min-device-pixel-ratio: 3/2),
    all and (min--moz-device-pixel-ratio: 1.5),
    all and (min-device-pixel-ratio: 1.5) {
        .class_name {
            background-image({{project.background_retina}});
        }
    }
</style>

【问题讨论】:

  • CSS 是静态的。如果你的风格真的很复杂,也许你需要一些 CSS 预处理器。

标签: css vue.js vuejs2


【解决方案1】:

当您使用 Vue.js 时,请使用 Vue.js 来更改背景,而不是 CSS:

var vm = new Vue({
    el: '#vue-instance',
    data: {
        rows: [
            {value: 'green'},
            {value: 'red'},
            {value: 'blue'},
        ],
        item:""
    },
    methods:{
        onTimeSlotClick: function(item){
            console.log(item);
            document.querySelector(".dynamic").style.background = item;
        }
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.16/vue.js"></script>
<div id="vue-instance">
    <select class="form-control" v-model="item" v-on:change="onTimeSlotClick(item)">
        <option value="">Select</option>
        <option v-for="row in rows">
            {{row.value}}
        </option>
    </select>
    <div class='dynamic'>VALUE</div>
    <br/><br/>
    <div :style="{ background: item}">Another</div>
</div>

【讨论】:

  • 很好,但在内联方法中,我无法为视网膜添加背景。我知道那种方法。
  • 你可以添加class、toggle、v-show、v-if来实现这个
  • 我可以用两个 div 和 class 来显示一个 div 是否依赖于视网膜。但是..它总是会加载两个图像。 v-if 或 v-show 听起来不错,但是如何使用 v-if 检查我们是否在视网膜显示器上?或者如何在JS中检查它。也许我会以这种方式找到解决方案。
【解决方案2】:

CSS &lt;style&gt; 是静态的。我不认为你可以这样做......你可能需要寻找不同的方法。

您可以尝试使用CSS variables。例如,(以下代码未经测试)

<template>
    <div class="class_name" :style="{'--bkgImage': 'url(' + project.background + ')', '--bkgImageMobile': 'url(' + project.backgroundRetina + ')'}">
    </div>
</template>

<style>
    .class_name{
        background-image: var(--bkgImage);
    }
    @media all and (-webkit-min-device-pixel-ratio : 1.5),
        all and (-o-min-device-pixel-ratio: 3/2),
        all and (min--moz-device-pixel-ratio: 1.5),
        all and (min-device-pixel-ratio: 1.5) {
            .class_name {
                background-image: var(--bkgImageMobile);
            }
        }
</style>

注意:只有最新的浏览器支持 CSS 变量

如果您仍然发现模板中的 :style 有任何问题,请尝试此操作,

<div :style="'--bkgImage: url(' + project.background + '); --bkgImageMobile: url(' + project.backgroundRetina + ')'">
</div>

【讨论】:

    【解决方案3】:

    包含动态样式的最佳方法是使用CSS variables。为了避免内联样式,同时获得动态样式的好处(或必要性——例如,数据负载中的用户定义颜色),在&lt;template&gt; 内使用&lt;style&gt; 标签(这样值可以通过Vue插入)。使用 :root pseudo-class 包含变量,以便在应用程序的 CSS 范围内可以访问它们。

    注意一些CSS值,like url()不能被插值,所以它们需要是完整的变量。

    示例(Nuxt.vueES6/ES2015 语法):

    <template>
    
    <div>
      <style>
        :root {
          --accent-color: {{ accentColor }};
          --hero-image: url('{{ heroImage }}');
        }
      </style>
      <div class="punchy">
        <h1>Pow.</h1>
      </div>
    </div>
    
    </template>
    <script>
    
    export default {
      data() { return {
        accentColor: '#f00',
        heroImage: 'https://vuejs.org/images/logo.png',
      }},
    }
    
    </script>
    <style>
    
    .punchy {
      background-image: var(--hero-image);
      border: 4px solid var(--accent-color);
      display: inline-block;
      width: 250px; height: 250px;
    }
    h1 {
      color: var(--accent-color);
    }
    
    </style>
    

    还在Codepen 上创建了一个更复杂的可运行示例。

    【讨论】:

    • 使用 在组件中尝试了您的解决方案并收到此错误:模板应该只负责将状态映射到 UI。避免在模板中放置带有副作用的标签,例如
    • 我和 Nelly 有同样的问题
    • 这是正确的想法,但正如 Nelly 指出的那样,Vue 会发出警告,甚至可能不会加载,具体取决于使用的版本(缩小的 Vue 似乎允许这样做)。请参阅 Muthu 的答案(特别是他们的更新部分)或 this SO answer 以获得更好的解决方案
    • 不是将 CSS 变量放在 &lt;style&gt; 块中,您可以构建一个对象,将每个变量名称作为属性,并将其值作为计算的 prop 或方法。然后简单地将这个对象绑定到根元素的style 属性。
    • 不幸的是,HTML 验证器会为
      标签内的
    【解决方案4】:

    我遇到了同样的问题。我一直在尝试使用数据库中的背景颜色值。我找到了一个很好的解决方案,可以在我从数据库中设置的内联 CSS 上添加背景颜色值。

    <img :src="/Imagesource.jpg" alt="" :style="{'background-color':Your_Variable_Name}">
    

    【讨论】:

    • 在 :style 中没有 { 和 } 也能正常工作
    • 如果您使用 lib,这将不起作用。我需要申请将样式应用于子组件的子组件。
    • 如果您不想将其括在额外的一对引号中,您也可以将background-color 写成蛇形大小写。看起来整洁又省时间:style="{backgroundColor:Your_Variable_Name}"
    【解决方案5】:

    是的,这是可能的。 Vue.js 不支持模板中的style 标签,但您可以通过使用component 标签来解决这个问题。未经测试的伪代码:

    在您的模板中:

    <component type="style" v-html="style"></component>
    

    在您的脚本中:

    props: {
        color: String
    }
    computed: {
        style() {
            return `.myJSGeneratedStyle { color: ${this.color} }`;
        }
    }
    

    您不应该使用这种方法的原因有很多。这绝对是 hacky,:style="" 在大多数情况下可能会更好,但对于您的媒体查询问题,我认为这是一个很好的解决方案。

    【讨论】:

      【解决方案6】:

      简单来说,这就是你在 Vue.js 和 Nuxt.js 中的做法:

      <template>
          <div>
              <img :src="dynamicImageURL" alt="" :style="'background-color':backgroundColor"/>
          </div>
      </template>
      
      <script>
          export default{
              data(){
                 return {
                       dynamicImageURL='myimage.png',
                       backgroundColor='red',
                  }
              }
          }
      </script>
      

      【讨论】:

      • 不起作用。说“解析错误”。
      【解决方案7】:

      我遇到了同样的问题,我想出了一个适合我(也许是你的)需要的 hack。

      由于&lt;style&gt; 包含在&lt;head&gt; 中,因此有一种方法可以使其工作:

      我们根据页面/组件的状态将 CSS 内容生成为计算属性

      computed: {
          css() {
              return `<style type="text/css">
               .bg {
                  background: ${this.bg_color_string};
               }</style>`
          }
      }
      

      现在,我们将样式设置为字符串,唯一的挑战是将其传递给浏览器。

      我将此添加到我的&lt;head&gt;

      <style id="customStyle"></style>
      

      然后我在页面加载后调用setInterval

       mounted() {
           setInterval(() => this.refreshHead(), 1000);
       }
      

      我这样定义 refreshHead:

      methods: {
         refreshHead() {
             document.getElementById('customStyle').innerHTML = this.css
         }
      }
      

      【讨论】:

        【解决方案8】:

        您可以使用 Vue.js 提供的组件标签。

        <template>
          <component :is="`style`">
            .cg {color: {{color}};}
          </component>
          <p class="cg">I am green</p> <br/>
          <button @click="change">change</button>
        </template>
        <script>
          export default {
            data(){
              return { color: 'green' }
            },
            methods: {
              change() {this.color = 'red';}
            }
          }
        </script>

        【讨论】:

          【解决方案9】:

          正如Vue.js 3.2 最近发布的那样,您现在可以像这样执行State-Driven Dynamic CSS

          <template>
              <h1 id="script">Script</h1>
              <h1 id="scriptSetup">Script setup</h1>
          </template>
          
          <script>
            export default {
              data() {
                return {
                  colorFromScript: 'red'
                }
              }
            }
          </script>
          
          <script setup>
          const colorFromScriptSetup = 'green'
          </script>
          
          <style>
            #script {
                color: v-bind('colorFromScript')
            }
          
            #scriptSetup {
                color: v-bind('colorFromScriptSetup')
            }
          </style>
          

          See an implementation here

          【讨论】:

          • 这是使用Vue 3的最佳解决方案。
          【解决方案10】:

          Vue 3 状态驱动的动态 CSS 变量

          我知道这有点晚了,并且正在使用 Vue.js 2,但到目前为止,在 Vue.js 3 中,您可以创建状态驱动的 CSS 变量。

          您现在可以使用 v-bind() 在样式标签中使用 SFC(单文件组件)状态数据。

          您可以阅读更多关于状态驱动的 CSS 变量 here,或阅读 Vue.js 3 文档 here

          这是一个代码示例

          示例

          <template>
            <div>
              <input type="text" v-model="color" />
              <div class="user-input-color">
                {{ color }}
              </div>
            </div>
          </template>
          
          <script>
          export default {
            data: () => ({
              color: 'white'
            })
          }
          </script>
          
          <style scoped>
          .user-input-color {
            background-color: v-bind(color)
          }
          </style>
          

          这是live example的链接。

          链接

          【讨论】:

          • 像魅力一样工作
          猜你喜欢
          • 1970-01-01
          • 2023-01-19
          • 2020-10-03
          • 2019-04-05
          • 1970-01-01
          • 2015-07-19
          • 1970-01-01
          • 2018-03-07
          • 2018-01-19
          相关资源
          最近更新 更多