将样式应用于 v-for 使用 Vuejs 动态添加的 HTML 元素

Apply style to an HTML element added dynamically by v-for using Vuejs

我正在使用 v-for 向列表动态添加元素。

<ol>
    <li v-for="light in lights">
        <input type="range" min="0" max="255" v-model="light.currentBrightness" v-on:change="setBrightness(light)" />
    </li>
</ol>

我想使用 rangeslider 装饰滑块。

问题是,在 DOM 初始化后添加新元素时,它没有采用 rangeslider.js 中指定的样式。解决此问题的方法是调用 rangeslider.js 中的重新初始化方法,这将重新装饰所有滑块元素。

我不确定在运行时动态添加元素时如何调用 javascript 方法。有人怎么做吗?对我来说,这似乎是一个非常普遍的问题,但我无法通过谷歌搜索找到解决方案。

我的问题与 github 中讨论的相同。

如果您是 JavaScript 和 Vue 的新手,那么您已经接近深度了。 rangeslider 不仅仅是样式(如 CSS),它是一个替换内置范围输入的小部件。

Vue 背后的一个基本思想是它控制着 DOM 而你只修改你的模型,但也有一些小心控制的例外。组件具有 lifecycle hooks,您可以在其中插入和修改组件拥有的 DOM 个元素。

Some instructions for v-model support:

So for a component to work with v-model, it should (these can be configured in 2.2.0+):

  • accept a value prop
  • emit an input event with the new value

所以我们制作一个组件,它的模板是一个范围输入元素。我们给它一个 value 道具。在 mounted 挂钩中,我们在输入元素上初始化范围滑块(作为 el 提供),然后将其设置为在更改时发出 input 事件。

new Vue({
  el: '#app',
  data: {
    lights: [{
        currentBrightness: 10
      },
      {
        currentBrightness: 30
      }
    ]
  },
  methods: {
    addRange: function() {
      this.lights.push({
        currentBrightness: 50
      });
    }
  },
  components: {
    rangeSlider: {
      props: ['value', 'min', 'max'],
      template: '<input min="{{min}}" max="{{max}}" type=range />',
      mounted: function() {
        var vm = this
        $(this.$el)
          .val(this.value)
          // init rangeslider
          .rangeslider({
            polyfill: false
          })
          // emit event on change.
          .on('change', function() {
            vm.$emit('input', this.value)
          })
      }
    }
  }
});
<link href="//cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.0/rangeslider.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.2/vue.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.0/rangeslider.min.js"></script>
<div id="app">
  <ol>
    <li v-for="light in lights">
      <range-slider v-model="light.currentBrightness" min="0" max="255"></range-slider>
      <div>{{light.currentBrightness}}</div>
    </li>
  </ol>
  <button @click="addRange">Add Range</button>
</div>

您可以使用以下 CSS 代码在 html5 范围输入中应用一些样式:

body {
    padding: 30px;
}
input[type=range] {
    /*removes default webkit styles*/
    -webkit-appearance: none;

    /*fix for FF unable to apply focus style bug */
    border: 1px solid white;

    /*required for proper track sizing in FF*/
    width: 300px;
}
input[type=range]::-webkit-slider-runnable-track {
    width: 300px;
    height: 5px;
    background: #ddd;
    border: none;
    border-radius: 3px;
}
input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    border: none;
    height: 16px;
    width: 16px;
    border-radius: 50%;
    background: goldenrod;
    margin-top: -4px;
}
input[type=range]:focus {
    outline: none;
}
input[type=range]:focus::-webkit-slider-runnable-track {
    background: #ccc;
}

input[type=range]::-moz-range-track {
    width: 300px;
    height: 5px;
    background: #ddd;
    border: none;
    border-radius: 3px;
}
input[type=range]::-moz-range-thumb {
    border: none;
    height: 16px;
    width: 16px;
    border-radius: 50%;
    background: goldenrod;
}

/*hide the outline behind the border*/
input[type=range]:-moz-focusring{
    outline: 1px solid white;
    outline-offset: -1px;
}

input[type=range]::-ms-track {
    width: 300px;
    height: 5px;

    /*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */
    background: transparent;

    /*leave room for the larger thumb to overflow with a transparent border */
    border-color: transparent;
    border-width: 6px 0;

    /*remove default tick marks*/
    color: transparent;
}
input[type=range]::-ms-fill-lower {
    background: #777;
    border-radius: 10px;
}
input[type=range]::-ms-fill-upper {
    background: #ddd;
    border-radius: 10px;
}
input[type=range]::-ms-thumb {
    border: none;
    height: 16px;
    width: 16px;
    border-radius: 50%;
    background: goldenrod;
}
input[type=range]:focus::-ms-fill-lower {
    background: #888;
}
input[type=range]:focus::-ms-fill-upper {
    background: #ccc;
}