vue 组件状态冲突

原创 2018年04月16日 15:36:42

vue 组件状态冲突

在写vue组件Carousel 时,出现在同一个页面中多次使用同一个组件时的状态冲突,原因是过多的使用了JavaScript原生的DOM操作方式,修改使用vue中ref 操作DOM元素后,则此冲突消失;

vue中对于ref的解释为:ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例.

<template>
    <div class="yu-carousel" ref="carousel"
         :class="[type]"
         :style="{width:width,height:height}">
      <ul class="yu-img-warp" ref="warp">
        <slot/>
        <yu-carousel-item :src="lastSrc" v-if="!type"/>
      </ul>
      <ol v-if="!type" ref="lines">  //***添加 ref 用于操作DOM元素***
        <li v-for="(value,index) in items"></li>
      </ol>
      <div class="carousel-arrow">
        <a  ref="left" href="javascript:;" class="left_arrow"><i class="iconfont icon-angle-left"></i></a>
        <a  ref="right"  href="javascript:;" class="right_arrow"><i class="iconfont icon-angle-right"></i></a>
      </div>
    </div>
</template>
<script>
import YuCarouselItem from './carousel-item';

export default {
  name: 'YuCarousel',
  components: {
    YuCarouselItem,
  },
  props: {
    width: String,
    height: String,
    autoplay: false,
    interval: Number,
    type: String,
    position: null,
  },
  data() {
    return {
      items: 0,
      lastSrc: String,
    }
  },
  methods: {
  },
  mounted() {
    //  动画函数
    function animate(element, target, num) {
      num = num || 10;
      clearInterval(element.timer);
      element.timer = setInterval( () => {
        let leader = element.offsetLeft;
        let step = target > leader ? num : -num;
        if (Math.abs(target - leader) >= Math.abs(step)) {
          leader += step;
          element.style.left = leader + "px";
        } else {
          clearInterval(element.timer);
          element.style.left = target + "px";
        }
      }, 15);
    }
    function animate1(element, obj, fn){
      clearInterval(element.timer);
      element.timer = setInterval(() => {
        let flag = true;
        for(let k in obj) {
          let style = k;
          let target = obj[k];
          if (k === 'opacity') {
            let leader = getStyle(element, style);
            leader = parseFloat(leader) || 0;
            leader *= 1000;
            target *= 1000;
            let step = (target - leader)/10;
            step = step>0?Math.ceil(step):Math.floor(step);
            leader += step;
            element.style[style] = leader / 1000;
            if (leader !== target) {
              flag = false;
            }
          } else if (k === 'zIndex') {
            element.style.zIndex = target;
          } else {
            let leader = getStyle(element, style);
            leader = parseInt(leader) || 0;
            let step = (target - leader) / 10;
            step = step > 0 ? Math.ceil(step) : Math.floor(step);
            leader += step;
            element.style[style] = `${leader}px`;
            if (leader !== target) {
              flag = false;
            }
          }
        }
        if (flag) {
          clearInterval(element.timer);
          fn && fn();
        }
      }, 15);
    }
    function getStyle(element, style) {
      if ('getComputedStyle' in window) {
        return window.getComputedStyle(element, null)[style];
      } else {
        return element.currentStyle[style];
      }
    }
    let lines = null;
    const carousel = this.$refs.carousel;
    const ul = carousel.children[0];
    const leftArrow = this.$refs.left;
    const rightArrow = this.$refs.right;
    const imgs = ul.children;
    const imgWidth = carousel.offsetWidth;
    let lock = true;
    const arr = this.position;
    let count = 0;
    let timer = null;
    if (!this.type) {
      this.$nextTick(() => {
        lines = this.$refs.lines.children;
        lines[0].className = 'now';
        console.log(lines);
        // 小圆点
        for (let i = 0; i < lines.length; i++) {
          lines[i].index = i;
          lines[i].addEventListener('click', () => {
            for (let j = 0; j < lines.length; j++) {
              lines[j].className = '';
            }
            lines[this.index].className = 'now';
            animate(ul, -this.index * imgWidth, 50);
          })
        }
      });
    }
    this.lastSrc = this.$children[0].src;
    this.items = this.$children.length - 1;
    this.$refs.warp.style.width = `${this.$children.length}00%`;
    // const list = document.querySelectorAll('.yu-img-warp li');  **有冲突时的代码**
    const list = this.$refs.warp.children;   // **修改之后 无冲突,使用啦 ref操作DOM元素**
    for (let i = 0; i < list.length; i++) {
      list[i].style.width = `${(1 / this.$children.length) * 100}%`;
    }
    //  轮播图
    if (this.type) {
      for (let i = 0; i < imgs.length; i++) {
        animate1(imgs[i], arr[i]);
      }
    }
    rightArrow.addEventListener('click', () => {
      //  普通轮播图
      if (this.type) {
        if (lock) {
          lock = false;
          arr.unshift(arr.pop());
          for (let i = 0; i < imgs.length; i ++) {
            animate1(imgs[i], arr[i], () => {
              lock = true;
            })
          }
        }
      } else {
        if (count >= imgs.length - 1) {
          ul.style.left = 0;
          count = 0
        }
        count += 1;
        animate(ul, -count * imgWidth, 50);
        for (let i = 0; i < lines.length; i++) {
          lines[i].className = '';
        }
        if (count >= imgs.length - 1) {
          lines[0].className = 'now';
        } else {
          lines[count].className = 'now';
        }
      }
    });
    //  左箭头
    leftArrow.addEventListener('click', () => {
      if (this.type) {
        if (lock) {
          lock = false;
          arr.push(arr.shift());
          for (let i = 0; i < imgs.length; i++) {
            animate1(imgs[i], arr[i], () => {
              lock = true;
            })
          }
        }
      } else {
        //  普通轮播图
        if (count <= 0) {
          count = imgs.length - 1;
          ul.style.left = `${-count * imgWidth}px`;
        }
        count -= 1;
        animate(ul, -count * imgWidth, 50);

        for (let i = 0; i < lines.length; i++) {
          lines[i].className = '';
        }
        lines[count].className = 'now';
      }
    });
    //  line

    //  自动播放
    let that = this;
    function auto() {
      timer = setInterval(() => {
        rightArrow.click();
      }, that.interval);
    }
    if (this.autoplay) {
      auto();
      carousel.onmouseover = () => {
        clearInterval(timer);
      };
      carousel.onmouseout = () => {
        clearInterval(timer);
        auto();
      }
    }
  },
}
</script>
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/youngjqz/article/details/79961406

MVC4使用VueJS入门

Home视图文件夹Index.cshtml@{ ViewBag.Title = "主页"; } ASP.NET
  • WuLex
  • WuLex
  • 2017-08-02 22:44:36
  • 4890

vue plugin 插件编写以loading为例

我们在使用vue开发的过程中,经常会遇到这两个问题: 我要使用loading(加载动画) toast(浮层提示) dialog(弹框提示)之类的全局性组件,但是用全局组件注册的话非常麻烦,还要在tem...
  • sjn0503
  • sjn0503
  • 2017-07-16 17:21:50
  • 4851

Vue插件写、用详解(附demo)

Vue插件 出处http://blog.csdn.net/qq20004604 1、概述 简单来说,插件就是指对Vue的功能的增强或补充。 比如说,让你在每个单页面的组件里,都...
  • sinat_17775997
  • sinat_17775997
  • 2017-09-13 13:57:51
  • 556

vue的组件stylea样式污染冲突问题

子元素的 根元素 会继承父元素的 ScopeId
  • qq_16390749
  • qq_16390749
  • 2018-03-22 10:28:34
  • 51

解决vue样式冲突的问题

在style里 添加scoped用这种方式相当于在页面上加入了唯一标示。
  • u014196765
  • u014196765
  • 2017-09-18 11:41:04
  • 495

Vuejs(16)——Vue插件写、用详解(附demo)

Vue插件写、用详解(附demo)
  • qq20004604
  • qq20004604
  • 2017-02-24 23:33:25
  • 11207

VUE开发项目遇到的一些问题(一)

遍历树形json数据var root = [{ name:'D盘', children:[{ name:'学习'...
  • qq_22844483
  • qq_22844483
  • 2018-01-03 22:00:29
  • 236

vue之django 和vue语法冲突处理

修改vue.js的默认的绑定符号Vue.config.delimiter=['[[',']]'];
  • qq_33733970
  • qq_33733970
  • 2017-12-04 08:42:54
  • 246

Vue中状态管理——Vuex

vuex是一个专门为vue.js设计的状态管理模式,并且也可以使用devtools进行调试。在vuex出现之前,vue里面的状态是属于‘单向数据流’。举个官网的例子:new Vue({ // ...
  • qq_35534823
  • qq_35534823
  • 2017-05-05 02:13:41
  • 7317

Vue系列——在vue项目中使用jQuery及其第三方插件

最近学习Vue.js做一个后台管理系统,采用 vue-cli 脚手架搭建,Element作为UI框架。然后想在项目中自定义滚动条,舍弃浏览器原生滚动条,成熟的现成插件也只找到了jQuery的,所以不得...
  • mr_wuch
  • mr_wuch
  • 2017-04-19 14:10:10
  • 18997
收藏助手
不良信息举报
您举报文章:vue 组件状态冲突
举报原因:
原因补充:

(最多只允许输入30个字)