Wrapping Switchery in a Directive VueJS

心已入冬 提交于 2019-12-12 03:36:23

问题


I am trying to wrap the Switchery iOS 7 in a Vue Directive but I had no success until now! Somebody to help me?

There is my code fiddle.

JS

Vue.directive('plSwitchery', {
  twoWay: true,

  deep: true,

  params: [],

  bind: function() {

    var self = this,
      value = self.value,
      el = self.el;

    el.checked = true;

    new Switchery(el);

    $(el).on('change', function(a) {
      value = !value;
      self.set(value);
      alert(self.value);
    });

  },
  update: function(value) {
    window.console.log('directive update');
  },
  unbind: function() {
    this.el.destroy();
  }
});

var vm = new Vue({
  el: '#app',
  data: {
    selected: 1,
  },
  methods: {
    onChange: function() {
      alert('Do HTTP request');
    }
  }
});

HTML

<div id="app">

  <input type="checkbox" v-pl-switchery="selected" />

</div>

So I could wrap it and it's partially working... Now I need to know how to update my SELECTED data and how to call the method onChange when the user trigger the change event to call the server and update some information on the database!

I don't really get how to deal with it!

Thanks in advance!


回答1:


The quick way would be to do: this.vm.onChange(), but that makes it nessessary for the parent component to have a method by that name, and restricts the reusability of that directive.

Another way would be to simply create a watch in the component and maybe move the onChange funciton from methods: to watch::

watch: {
  'selected': function() {
    alert('Do HTTP request');
  }
}

Third option would be to $emit an event in the component from the directive:

// in the directive
this.vm.$emit('swicth-changed',value)

//if you have different switches you can name them with the directive argument:

// v-pl-switchery:name="selected" 

this.vm.$emit('switch-changed',this.arg,value) // this.arg gives you the 'name'

<input type="checkbox" v-pl-switchery="selected" @switch-changed="onChange"/>

For your situation I would go with the simple second approach




回答2:


Actually I gave up Switchery plugin and I've made my own component!

There is my solution!

JS

Vue.component('plSwitch', {
  template: '#ck',
  props: {
    model: {
      default () {
        return false
      }
    },
    text: {
      default () {
        return;
      }
    },
    disabled: {
      default () {
        return false
      }
    }
  },
  methods: {
    onChange() {
      console.log('oi')
      vm.$dispatch('onChange')
    }
  }
})

var vm = new Vue({
  el: '#add',
  data: {
    state: true
  },
  events: {
    onChange: function() {
      alert('Do HTTP request');
    }
  }
})

CSS

.label_switch {
  display: inline-block;
  margin: 0;
  cursor: pointer;
  font-weight: normal;
  position: relative;
}
.label_switch input[type="checkbox"] {
  position: absolute;
  -webkit-appearance: none;
  appearance: none;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.label_switch input[type="checkbox"] + span {
  display: inline-block;
  width: 38px;
  height: 18px;
  position: relative;
}
.label_switch input[type="checkbox"] + span:before {
  content: "";
  display: block;
  width: 38px;
  height: 22px;
  border-radius: 20px;
  border: 1px solid #dfdfdf;
  -webkit-transition: all 0.1s ease-out;
  transition: all 0.1s ease-out;
}
.label_switch:hover input[type="checkbox"] + span:before {
  box-shadow: inset 0 0 15px #eee;
}
.label_switch input[type="checkbox"] + span:after {
  content: "";
  position: absolute;
  top: 0px;
  left: 0;
  display: block;
  width: 22px;
  height: 22px;
  -webkit-transition: all 0.3s ease-out;
  transition: all 0.3s ease-out;
  background: #fff;
  border-radius: 20px;
  border: solid 1px #dfdfdf;
  box-shadow: 2px 1px 1px -2px rgba(0, 0, 0, 0.4)
}
.label_switch input[type="checkbox"]:checked + span:after {
  left: 18px;
  border: solid 1px #5FBEAA;
  box-shadow: none;
}
.label_switch input[type="checkbox"]:checked + span:before,
.label_switch input[type="checkbox"]:disabled:checked + span:before {
  border: 1px solid #5FBEAA;
  background-color: #5FBEAA;
}
.label_switch:hover input[type="checkbox"]:checked + span:before {
  box-shadow: none;
}
.label_switch input[type="checkbox"]:disabled + span {
  opacity: 0.6;
}
.label_switch input[type="checkbox"]:disabled + span:before {
  background-color: #f7f7f7;
}
.label_switch input[type="checkbox"]:disabled + span:after {
  background-color: #f3f3f3;
}
.label_switch input[type="checkbox"]:disabled + span:after {
  background-color: #fff;
}
.label_switch input[type="checkbox"]:disabled + span:before,
.label_switch input[type="checkbox"]:disabled + span:after {
  cursor: no-drop;
}
.label_switch input[type="checkbox"]:disabled:checked + span:before {} .m-r-5 {
  margin-right: 5px !important;
}
.m-l-5 {
  margin-left: 5px !important;
}
.disabled {
  cursor: no-drop!important;
}

HTML

<template id="ck">
  <label class="label_switch" :class="{ 'disabled' : disabled }">
    <input type="checkbox" v-model="model" :false-value="false" :true-value="true" :disabled="disabled" @click="onChange()">
    <span :class="{ 'm-r-5': text != '' }"></span> {{ text }}
  </label>
</template>

<div id="add">
  <pre>{{ $data | json }}</pre>
  <pl-switch :model.sync="state" text="Example"></pl-switch>
</div>

Let me know you do you guys think!



来源:https://stackoverflow.com/questions/36586066/wrapping-switchery-in-a-directive-vuejs

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