最开的网页只有文字,也就html部分,随着互联网发展,网页内容的丰富多彩,网页不仅仅限于浏览,而是需要互动。为解决这个问题,先后出现了js和css。
解决这个问题的思路,各有利弊:
1.优点
css很灵活,程序员可以有能力随心所欲的控制网页。
JS很强大,可以随心所欲的控制用户的行为。
分工明确,更容易专业化,符合社会趋势,越来越精细化。
2.缺点
分工必然会涉及到协作,协作必然会存在这样的问题:怎么让沟通和切换工作场景状态保持一致。
举个现实的例子,你把一个前端项目分给三个人做,一个人切图,一个人数据交互,一个写后台。那么如果切图的人改网页上的东西,一定会影响另外两个人,怎么保证三个人修改页面状态一致,这就是个问题。
根本性的解决方案
web components
解决问题的思路:
让网页由一个个积木组成,每一个积木通过良好的定义规定好接口和规范,以及统一的实现。这个本质上和我们用同一个型号的砖头可以盖出不同的房子没什么两样。
目前问题:
兼容性不好、思路不成熟、不好用
普遍的解决方案
1.mvc方案
MVC很简单,还是拿刚才的三个人工作举例:
现在写数据交互的人说了,切图的你啥也不用想,你就按照我们商定的标准切图,别瞎搞。后台你也是,我想要啥数据你就给我啥格式,别自己瞎搞,我统一去合并文件。
这就是MVC思想,纯切图的就是view,写后台搞数据的就是model,写数据交互让前后台对应起来的就是c。
MVC的初衷是好的,
MVC要实现的目标是将软件用户界面和业务逻辑分离以使代码可扩展性、可复用性、可维护性、灵活性加强。
结果有两个问题:
1.很多程序员将MVC当成了三层架构在用,写出来的东西既不是三成架构也不是MVC,倒是像一个什么都不是的四不像。三层架构的核心思想是面向接口编程和各层之间的解耦和可替换性,MVC并不具备这样的思想和能力,很多人误解了它。
2.即使不误解,这样做也有问题从我们的例子可以看出来,C端业务过重,一来造成混乱,二来对C端业务能力要求也高。Controller会越来越难维护
3.手动管理各个过程很费劲。
举个例子:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script> window.onload = function(){ var oUl = document.getElementById('ul1'); var aPrev = document.querySelectorAll('.prev'); var aNext = document.querySelectorAll('.next'); for(var i=0;i<aPrev.length;i++){ aPrev[i].onclick = function(){ var oParent = this.parentNode; var oPrev = oParent.previousElementSibling || oParent.previousSibling; if(oParent == oUl.children[0]){ alert('到头了!'); return; } oUl.insertBefore(oParent,oPrev); } } for(var i=0;i<aNext.length;i++){ aNext[i].onclick = function(){ var oParent = this.parentNode; var oNext = oParent.nextElementSibling || oParent.nextSibling; var oNext2 = oNext.nextElementSibling || oNext.nextSibling; if(oParent == oUl.children[oUl.children.length-1]){ alert('到底了!'); return; } oUl.insertBefore(oParent,oNext2); } } }; </script></head><body> <ul id="ul1"> <li> <span>1、111111111</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> <li> <span>2、222222222</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> <li> <span>3、3333333333</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> <li> <span>4、4444444444</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> <li> <span>5、5555555555</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> </ul></body></html>
效果:
即使用MVC的方式,也会涉及到大量的过程管理,DOM操作,比如用控制器控制上下移动,既要考虑元素位置,也要考虑点击按钮的行为。整个过程繁琐、复杂。
2.react方式
那我们换一个思路,有没有可能我只考虑数据的变化,DOM的操作不考虑。比如:
我现在根本就不去想插到谁后面的后面的前面,我只考虑一件事,我把四条数据看做一个数组中的数据,上下移动我玩的就是数组,数组对了,那么位置不就正确了吗?这就是react的方式。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script> window.onload = function(){ var aEles = document.getElementsByTagName('li'); var oUl = document.getElementById('ul1'); arrAEles = [...aEles]; var aPrev = document.getElementsByClassName('prev'); for(let i = 0;i<aPrev.length;i++){ //上移 //[1,2,3,4] =>[2,] aPrev[i].onclick = function(){ if(i ==0){ alert('到顶了'); return; } //这里我只是说明,我们可以只考虑数据顺序 [arrAEles[i],arrAEles[i-1]] = [arrAEles[i-1],arrAEles[i]]; SortEles(arrAEles); }; } var aNext = document.getElementsByClassName('prev'); //我们根本不用管DOM 怎么操作的 function SortEles(arrAEles){ oUl.innerHTML = ''; for(var i = 0;i<arrAEles.length;i++){ oUl.appendChild(arrAEles[i]); } } }; </script></head><body> <ul id="ul1"> <li> <span>1、111111111</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> <li> <span>2、222222222</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> <li> <span>3、3333333333</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> <li> <span>4、4444444444</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> <li> <span>5、5555555555</span> <a href="javascript:;" class='prev'>上移</a> <a href="javascript:;" class='next'>下移</a> </li> </ul></body></html>
这里我们只是实现了一个思路,并没有具体去实现,但是大家已经能感受到不操作DOM的好处。
一句话:数据对了,什么都对了。所谓的react状态管理,其实就是数据管理。
结语:
- 首先我们说了HTML、css、JS分离造成问题,促使了React的出现;
- 然后我们了解了根本解决方案(web components )需要面对的问题;
- 接着我们讲了普遍解决方案,mvc的方式;
- 最后我们说了为什么最终大家走到了react方式这一步。
下一篇文章我们聊聊React是什么,以及React组件化的实现。