<h3>需求分析</h3>
<ul>
<li><b>两个区域:</b>
<ul>
<li>操作区域:可供操作的区域</li>
<li>呈现区域:将数据可视化的区域</li>
</ul>
</li>
<li><b>两个模块</b>(操作区域内):
<ul>
<li>输入模块:可供数据输入的模块</li>
<li>功能模块:可选功能的模块</li>
</ul>
</li>
<li><b>五个功能</b>(功能模块内):
<ul>
<li>数据插入功能</li>
<li>数据删除功能</li>
<li>随机生成数据功能(1~100)</li>
<li>数据排序功能(冒泡排序)</li>
<li>数据打乱排序功能</li>
</ul>
</ul>
<h3>功能实现设想</h3>
<h5>流程图</h5>
<h3>具体实现分析</h3>
<strong>基本思路:将数据储存在数组dataList[ ]中,根据需求对数组进行操作,并将操作后的数组渲染在网页上(即数据可视化)</strong>
<h5>实现过程</h5>
<ol>
<li>添加函数
<ul>
<li>渲染函数
渲染函数主要是通过dom操作,将数据添加到文档中。关于数据可视化,我采用的方式是以div作为一个数据bar,根据数据的大小不同,动态地给每个div设定高度,并且给每个div添加背景颜色,这样,在网页上看起来,就和柱状图一样了。
<pre><code>
function render(){
var numList = document.getElementById("num-list");
//每次调用渲染函数都将原numList里内容清空并重新渲染
numList.innerHTML = "" ;
for(var m = 0; m < dataList.length; m++){
numList.innerHTML += "<div>" + "</div>" ;
//取得包含数据的div的nodelist
var dataDiv = numList.querySelectorAll("div");
//给每个数据的div设定高度
dataDiv[m].style.height = dataList[m]*5 + "px";
}
}
</code></pre>
</li>
<li>打乱排序函数
因为js的数组十分强大,自带<code>sort()</code>方法,所以我们只需要随机生成-1(正序)或者1(倒序),sort方法会自动帮我们对数组进行处理。
<pre><code>function randomSort(){
return Math.random()>0.5?-1:1;
}
</code></pre>
</li>
<li>随机生成函数
与打乱排序函数相同,这个函数里同样使用了<code>Math.random()</code>方法,这个方法随机生成[0,1)范围内的数字,只要稍作变化,便能得到想要的[1,100]内的随机数。
<pre><code>
function randomGeneration(){
for(var x=0; x<19; x++){
dataList[x] = parseInt(Math.random()*100+1);
}
}
</code></pre>
</li>
<li>冒泡排序函数
<pre><code>
function sortNum(arr){
for (var i = arr.length-1; i > 0; i--) {
for(var j = 0; j < i; j++){
if (arr[j] > arr[j+1]) {
var temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
//将每一次交换的数组存到state中,state是数组的数组
state.push(JSON.parse(JSON.stringify(arr)));
}
}
}
}
</code></pre>
关于这个排序函数,其实没有太多需要描述的地方,就是一个很简单的冒泡排序。值得一提的是,后面的state是一个数组,通过JSON数据格式,将每一次移动后原来数据的状态储存到了state中,在后面我们会根据这个state进行操作,以实现数据bar随着排序过程移动的视觉效果。
</li>
</ul>
</li>
<li>给各个按钮绑定事件
设定一个初始函数<code>init()</code>,在<code>init()</code>中给各个按钮绑定事件,然后在最后调用<code>init()</code>函数即可。
<pre><code>
btn.onclick = function(){
//添加事件
}
</code></pre>
具体来说,一共有七个按钮,来实现五个功能,他们分别是:<b>向左插入数据、向右插入数据、从左边删除数据、从右边删除数据、冒泡排序、打乱排序、随机生成数据。</b>
<ul>
<li>向左插入数据
先使用dom操作获得用户输入的数据,然后通过数组的<code>unshift()</code>方法,将数据从数组坐标较小的那一方(即前方/左方)插入数组,然后将数组渲染在页面上。
<pre><code>
inleftBtn.onclick = function(){
var data = document.getElementById("num- input").value.trim();
dataList.unshift(data);
render();
}
</code></pre>
向右插入数据的操作同理,区别在于使用的是数组的<code>push()</code>方法。
</li>
<li>从左边删除数据
删除数据的操作与插入数据的操作也很相似,原理也是对数组进行处理之后,进行渲染。
<pre><code>
outLeftBtn.onclick = function(){
var data = document.getElementById("num-input").value.trim();
dataList.shift(data);
render();
}
</code></pre>
<code>shift()</code>方法帮助我们从数组前方(视觉效果为左)删除数组元素。从右边删除数组使用<code>pop()</code>方法。
</li>
<li>冒泡排序
<pre><code>sort.onclick = function(){
sortNum(dataList);
var int = setInterval(forSortRender, 100);
//专门给冒泡排序写一个渲染函数
function forSortRender(){
var s ;
s = state.shift();
var numList = document.getElementById("num-list");
numList.innerHTML = "" ;
if (s !== undefined) {
for(var m = 0; m < s.length; m++){
numList.innerHTML += "<div>" + "</div>" ;
//取得包含数据的div的nodelist
var dataDiv =
numList.querySelectorAll("div");
//给每个数据的div设定样式
dataDiv[m].style.height = s[m]*5 + "px";
}
}
//避免state为空之后,页面也变空
else{
render();
window.clearInterval(int);
}
}
}</code></pre>
之前我们提到,在写冒泡排序函数的时候,创建了一个state数组,用来存储每一趟排序后的数组状态,现在就到了它派上用场的时候。在我们专门为排序过程写的渲染函数中,<code>shift()</code>方法弹出state中第一个数组,即进行了第一次交换后的数组,并返回它,用变量s来保存。此时将s中的数据依次渲染在页面上。<code>setInterval()</code>方法会每隔100ms调用一次这个渲染函数。于是在100ms之后,state又弹出最前面的一个数组,这个数组是原来的dataList[ ]进行了两次交换之后的数组,将它渲染出来,我们在视觉上就形成了数据bar在移动的错觉。
这样,在弹出了交换次数个数组之后,state[ ]变为空,s取不到任何值,就有可能出现排序完成后页面突然变空得情况。于是设置if条件,当s的值为undefined时,使用原来的渲染函数<code>render()</code>渲染排好序的原数组dataList[ ],并且使用<code>clearInterval()</code>停止调用专门给排序写的<code>forSortRender()</code>函数。
</li>
</ul>
</li>
</ol>
<h3>待改进的地方</h3>
<ol>
<li>点击事件实现得很不优雅,每一个按钮都要写一串<code>onclick()</code>,如果使用<code>addEventLister()</code>方法大概会好很多</li>
<li>用一个div盒子实现数据bar似乎有些简单粗暴?暂时没想到更好的方法</li>
<li>渲染函数写了两次,这个有点明显的要功能不要性能的意思,应该可以改进。</li>
<li>在用户输入数据时未作处理,可能收到非法字符。这个是待添加的功能,因为正则表达式没有系统地学习,想找机会认真地学习一遍再来改。</li>
<li>待添加其他几种排序方式,如快排、简单选择排序等,顺便巩固数据结构的知识</li>
<li>待改进样式,待添加颜色选择功能。前端工作者不论何时对于自己手里出来的界面都不能马虎才是!
</li>
</ol>
<h3>总结</h3>
这次demo练习学到了不少js和dom方面的知识,小白表示很满足,但是实现得比较糙,需要改进的地方也很多,学习之路任重道远,加油↖(ω)↗
<h3>demo地址</h3>
https://github.com/escawn/dailyDemo/tree/master/jsVisualSort