实际上来说,我们学习的所有东西,最终一个的目的,就是用它来写东西,来做事的。
所以尽管面向对象,我们现在才刚刚开始,但是我们可以用它来做点小东西,比如做一个列表。
先给大家看下成品效果:
像这样的一个列表,如果我想用类来实现,这是特别常见的一个情况。
比方说我这个列表,它不光有热门主播,还可能有热门音乐,热门新闻等等一系列的。
所以它是一个非常有重用需求的这么一个东西,那么在这种情况下,我就想看看,用类的方式来完成它,会是怎样的一种感觉。
我们先来稍微来看一下 index.html 里面的一些布局,样式就不贴出来了,就是一个排列和间隔区分开来。
你可以看到,它整个就是一个大的 div,叫 hot-host。
然后下面有个 div,展示它的名字 title。
还有个 ul,里面三个一样的 li。
那么我们直接开始,如果我想要来用一个类来表述这个事情,那你要注意了:
首先,任何一个类,不是说你拿过来直接开始写就完事了。不是的,这种方法是最低效的。
我们一上来就要考虑清楚,要先想,想什么呢?
我得看看,它到底包括一些什么样的属性,以及包括一些什么样的方法。
当然,你可能会说,我不知道怎么想。
其实非常的简单,你就看一看,要求你有什么功能就行了。比方说,像我现在这个东西,可能没太多要求,我的要求就是你给我弄出来就行,所以现在这时候就可以不用设计那么多的方法出来。
当然顺便一说,这里有个小技巧。
我一般习惯于先考虑功能,因为功能其实就代表了这个类的方法。
比如,我们现在来假想一下,这个列表它有这么几个功能:
1,得能够从服务器去加载数据,,那我可能就得给它一个 reload 方法。
2,然后这个列表,可能要动态的往里面去添加东西,所以我可以多一个添加方法 add 。或者叫 push,名字你自己取,有就行。
3,然后也可能有删除,比如 remove。
所以说白了,如果我们想要去设计一个类的话,我的建议非常的简单:
你先别写,第一件事你得先琢磨,先想想你都有什么样的功能。
而根据功能,你就可以推算出要写什么方法了。
比方说你们产品设计了,我得能够往里面添东西,那我就有一个添加方法。
再说的更实在一点,有没有一个这样的可能:
在一开始的时候,就把这个类它里面所有,该有的方法,该有的属性,全部都设计的特别合理。并且在你们这个项目整个的生存周期之内,比如说这项目存在 5 年 10 年的,那这些代码一个字不用动。
这个是不太可能的。
说白了,我们一上来设计完之后,可能就算是一草稿。
然后,你在做的过程当中才会发现,哎呀,少一个修改,得加一个。
这种情况才是非常正常的,如果不出这事才奇怪,才有问题。
所以说,我们一开始考虑个七七八八,然后在做的过程中,和产品调整需求的过程当中,这个东西逐渐再来动。
这里稍微啰嗦下,因为我认为设计好一个类,比写好一个类还要重要。
实际上来说,我们真正去设计一个类的时候,我认为其实是一个自上而下的过程,什么叫自上而下呢?
首先,一开始我们考虑的是,你得先明白,这个类是干什么用的。
比如说我现在就对应的上面那个列表,那在这过程当中:
第一,我考虑它都对外提供哪些功能。
注意,这个时候,我还不考虑哪些方法,目前就考虑这个类有哪些功能。因为你的每一个功能,有可能并不一定只靠一个方法。
然后第二,有了功能了,我们在来分解,在看看,它都需要哪些方法。
第三,在这些方法的过程当中,在考虑我可能会用到哪些数据,也就是属性。
这时候大概就七七八八,能出来了。
所以,我个人一般都是这个思路:
1,功能。
2,方法。
3,数据。
那么接下来,我们就用这个套路来看下,这个东西怎么做:
首先第一个问题,我们的功能都有哪些?
第一,可能要能修改标题。
第二,列表的内容和数据需要能设置。
第三,可能要重新的去渲染这个列表。比方说数据变了,或者怎么着。
那么接下来,我们就来考虑下,都需要哪些方法。
首先,修改标题,那我们是不是可以对外提供一个 setTitle。当然,根据绝大多数的经验来说,set 跟 get 是相对的,就是说有 set,一般就有 get,所以 getTitle 也可以有。
再接下来,我们要能够去设置列表的数据,那我就叫 setData。名字都无所谓,因为上一篇博客我们也说了,类,它其实就是一个命名的空间。所以在这里面,你的名字可以不用考虑。比如我外面还有一个 setData,没关系,类里面是一个独立的空间。
然后我还需要能重新渲染,那就叫它 render。
再接下来,我们就可以考虑考虑,需要什么样的数据。
因为我们这边有 setTitle,所以我肯定得有一个 title 数据。
然后 setData,那么我也需要一个 data 数据。
至于 render,它其实是个过程。它是根据这个 data,来重新的生成一遍 html 里面的东西,那么这个有没有必要去搞一个数据来支撑它?我认为没有。
所以这时候你就可以看到,数据对应的就这 2 个。
那么,我们就自上而下的设计出来了这些东西:
1,功能
i. 修改标题
ii. 设置列表数据
iii. 重新渲染
2,方法
i. setTitle() / getTitle()
ii. setData() / getData()
iii. render()
3,数据
i. title
ii. data
那么到了这一步,我们就已经可以开始干活了。
首先,我们先写个 class,既然是个列表,名字就叫 HotList,名字无所谓,只要不跟别人冲突就行。
接下来,我们就把上面设计好的属性,title 和 data 给加进去:
这里会有一个小问题,就是,在这我们写死了合适吗?
不合适。一般来讲都是动态的,所以在这个时候,我们有两种选择。
第一种,我们可以在初始化的时候给它个空的:
没问题,很多地方都可以这么干,然后什么时候变?
等到我们以后去 setTitle 的时候,再把新的 title 拿到这里面来:
没问题,这是一种方法,但是说句实话,你得考虑一个事。
我们所有的类,是为了什么?是为了用起来方便。
这个类,它肯定分成 2 种人,一种是写这个类的人,一种是用这个类的人。
那么反过来我问下大家:你是要方便去实现这个类的人呢,还是要方便用这个类的人?
肯定是为了方便用的人,这不用想。
那么在这个情况下,你不光要考虑自己写起来怎么样,你还得考虑外面人怎么用。
像上面这种方法就比较麻烦。
所以,我们为什么不在一开始就搞个初始的参数,然后在 new 的过程当中,就可以直接给它这个东西了:
这样的话,外面用的人就比较灵活,既可以一上来就给,也可以一上来不给。然后等到什么时候想给的时候,再用 setTitle 去设置。
然后接下来,有 set 一般就有 get,这是一个习惯。
再接下来,我们就要正式的来做 render 这个东西了,那么这个 render 怎么做呢?
其实对于上面一大串 html 来说,很简单,我就是要生成它里面的代码:
这里面的 html,给它生成就行了,当然以后我们还会用到什么虚拟DOM,按需渲染啥的,现在我们先基础点。
首先,在 render 里面先创建2个东西:
1,div,就是它的那个标题。
2,ul,它里边 3 个一样的 li。
我们先把 div.hot-host 清空,并且复制一份,放到右边对比着来看:
然后,我们要做的就是怎么把 li 加进去。
首先你得有数据吧,那么这里我就可以做个循环,在循环的过程当中,就可以创建一个又一个的 li 了。
所以,我们就在外面创建一个数组,然后在循环里边 push 字符串:
那这个字符串里面放的是什么呢?
放的就是右边 li 的内容,我可以把它整个复制过来:
当然,数据目前还没有,但是这里面我们也不能写死,我们先写成变量:
如果这人是 vip 的话,那就有个 vip 的标志,也就是那个 img 标签。如果不是,那就没有。所以在这就做了一个简单的三目判断。
如果 data.vip 是 true 的话,那么就有 vip 的 img,如果没有,就是空。
到现在这个时候,数组里面该有的东西都已经有了。
那么我们就可以把它直接 join 起来,变成一整个字符串,再塞到 ul 里面,就完事了:
那么到现在为止,有一个小问题,比如我们现在创建好了这个 list,那么我就想做一个 render:
可以看到,页面上什么东西也没有,为什么?
非常简单,现在是做了render,没错,但是这个 render 做的不对。
我们光是创建了 div 和 ul,然后就没了?创建的元素在怎么好,是不是也得插到父级里面去啊?
所以,你可以发现,我们这里是不是就少了一个参数,我们还需要一个 parent。
当然这时候可能有人说,这 parent 不用传,你直接写死 hot-host 就行了,但是有个问题,现在写死了不太好。
因为将来也可能是在别的地方用,所以这个 parent 是可以作为一个参数传进来的。
然后我们把 div 和 ul 都给加上去:
可以看到,现在大概就长成这个样子。
当然,因为没有数据,所以只显示了一个 title,并不是出问题了。
所以接下来,我们在给它添加一点数据:
可以看到,一个列表就算是出来了。
那么这就完成了吗?
没有,它是有很多很多的问题的。
所以下一篇博客开始,我们就一步一步的找出,并解决问题。