使用vue实现排序算法演示动画
原因是最近做的一个小需求涉及到排序。界面如下:因为项目使用了vue,所以实现方法很简单,忽略视图部分。它本质上是一个数组操作。代码如下:{//上移moveUp(i){//将位置i的元素移动到i-1lettmp=this.form.replayList.splice(i,1)this.form.replayList.splice(i-1,0,tmp[0])},//下移moveDown(i){//将位置i的元素移动到i+1lettmp=this.form.replayList.splice(i,1)this.form.replayList.splice(i+1,0,tmp[0])}}这样可以正常交换位置,但是是变异的,没有动画,所以不明显,所以一个coder的修身养性(其实上面太闲了)让我打开vue网站看到这个例子:https://cn.vuejs.org/v2/guide/transitions.html#%E5%88%97%E8%A1%A8%E7%9A%84%E6%8E%92%E5%BA%8F%E8%BF%87%E6%B8%A1这个例子我见过很多次了,但是一直没用过。这正是我想要的效果,所以一次性复制粘贴大法:这样会有一个exchange的过渡效果,如下:舒服多了。这个需求到这里就结束了,但是事情还没有结束,我突然想到,平时看一些算法文章的时候,一般都会加一些演示动画。感觉跟这个很像,那我是不是可以用这个来实现呢?当然有可能。实现算法演示动画先写基本布局和样式:{{item.value}}
list是sorted数组,当然已经处理过了,在真正的源数组中添加了一个唯一索引,因为列表中的每一项都需要一个唯一键才能正常转换:constarr=[10,43,23,65,343,75,100,34,45,3,56,22]exportdefault{data(){return{list:arr.map((item,index)=>{return{index,value:item}})}}}max是这个数组中的最大值,用于按比例显示高度:{computed:{max(){letmax=0arr.forEach(item=>{如果(item>max){max=item}})returnmax}}}其他样式自己用,显示效果如下:简约而不简单~,现在万事俱备,只需要让它动起来,排序算法有很多,不过我比较厉害,所以以冒泡算法为例。最简单的冒泡排序算法如下:{mounted(){this.bubbleSort()},methods:{bubbleSort(){letlen=this.list.lengthfor(leti=0;i
this.list[j+1]){//相邻元素的两两比较lettmp=this.list[j]//元素交换this.$set(this.list,j,this.list[j+1])this.$set(this.list,j+1,tmp)}}}}}但是这样写就不动了,瞬间给你安排好了:试试加个延迟:{mounted(){setTimeout(()=>{this.bubbleSort()},1000)}}刷新看效果:有动画,但这不是我们想要的,我们想要的应该是这样的:所以我们修改一下,因为for循环一开始执行就不会停止,所以需要把两个for改一下循环分为两个函数,这样可以控制每个循环什么时候执行:{bubbleSort(){letlen=this.list.lengthleti=0letj=0//内部循环letinnerLoop=()=>{//每个内部循环在执行下一个外部循环之前执行if(j>=(len-1-i)){j=0i++outLoop()returnfalse}if(this.list[j].value>this.list[j+1].value){让tmp=this.list[j]this.$set(this.list,j,this.list[j+1])this.$set(this.list,j+1,tmp)}//动画是500毫秒,所以每800毫秒执行下一个内循环setTimeout(()=>{j++innerLoop()},800)}//OuterloopletoutLoop=()=>{if(i>=len){returnfalse}innerLoop()}outLoop()}}这样就实现了每一步动画效果:但是这样不是很直观,因为一些相邻的邻居不需要交换时没有移动,不知道当前行中当前是哪两个,所以需要高亮显示当前正在比较交换的两个元素。首先,模板部分给当前被比较的元素添加类名,用于高亮:{{item.value}} js部分定义了一个数组sorts来加载当前正在比较的两个元素的唯一索引值:{data(){return{sorts:[]}},methods:{bubbleSort(){//...//内循环letinnerLoop=()=>{//每个内循环执行完后执行下一个外循环if(j>=(len-1-i)){//清除数组this.sorts=[]j=0i++outLoop()returnfalse}//比较当前正在比较的两个元素将索引放入数组this.sorts=[this.list[j].index,this.list[j+1].index]//...}//外层循环//...}}}修改后的效果如下:最后参考刚才的例子,突出显示排序的元素:{data(){return{sorted:[]}},methods:{bubbleSort(){//...//InnerloopletinnerLoop=()=>{//在执行下一个外循环之前执行每个内循环if(j>=(len-1-i)){this.sorts=[]//看这里,把排序好的元素加入数组就可以了this.sorted.push(this.list[j].index)j=0i++outLoop()returnfalse}//...}//外循环//...}}}最终效果如下:接下来我们看选择排序,也就是选择排序的算法:{selectSort(){for(leti=0;i