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

我的梦境 提交于 2019-12-24 09:11:03

问题


I'm adding elements to a list dynamically using 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>

I want to decorate the slider using rangeslider.

Problem is, when a new element is added after the DOM is initialized, it's not taking the style specified in rangeslider.js. Way to fix this is to call the reinitialize method in rangeslider.js which will redecorate all the slider elements.

I'm not sure how to call the javascript method when the element is added dynamically during the runtime. Does anyone how to do it? To me, it seems like a very common problem but I could not find a solution by Googling.

My issue is same as discussed in github.


回答1:


If you're new to JavaScript and Vue, you're diving in pretty close to the deep end. The rangeslider isn't just styling (like CSS), it's a widget that replaces the built-in range input.

One basic idea behind Vue is that it controls the DOM and you only modify your model, but there are some carefully controlled exceptions. Components have lifecycle hooks where you are allowed to insert and modify DOM elements owned by the component.

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

So we make a component whose template is a range input element. We give it a value prop. In the mounted hook, we initialize the rangeslider on the input element (made available as el), then set it up to emit input events on change.

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>



回答2:


You can use the below CSS codes to apply some stylings in the html5 range input:

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;
}


来源:https://stackoverflow.com/questions/42703527/apply-style-to-an-html-element-added-dynamically-by-v-for-using-vuejs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!