[DIV/CSS] Vue.js 开发实践:实现精巧的无限加载与分页功能
Posted 浊酒映清泪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[DIV/CSS] Vue.js 开发实践:实现精巧的无限加载与分页功能相关的知识,希望对你有一定的参考价值。
本篇文章是一篇Vue.js的教程,目标在于用一种常见的业务场景——分页/无限加载,帮助读者更好的理解Vue.js中的一些设计思想。与许多Todo List类的入门教程相比,更全面的展示使用Vue.js完成一个需求的思考过程;与一些构建大型应用的高阶教程相比,又更专注于一些零碎细节的实现,方便读者快速掌握、致用。
需求分析当一个页面中信息量过大时(例如一个新闻列表中有200条新闻需要展示),就会产生问题,例如:
数据量过大,影响加载速度
用户体验差,很难定位到之前自己看过的某篇文章
扩展性差,如果200条变为2000条或者更多
所以常见的解决思路就是至底时加载数据或者分页展示。无限加载的实现过程类似于:
ajax类方法获取数据
数据存入本地数组
数组中的每条数据对应插入一个html模板片段中
将HTML片段append到节点中
前端分页的实现过程类似于:
ajax类方法获取数据
数据替换本地数组
数组中的每条数据对应插入一个HTML模板片段中
清空节点后将HTML片段append到节点中
往往修改或者维护代码时,我们会发现渲染HTML和插入部分是比较烦人的。因为我们需要将HTML拼接成字符串,在对应的位置插入数据,往往就是一段非常长的字符串,之后想要加个class都费劲。es6的模板字符串让这个情况有所好转,但是依然有瑕疵(例如实际编写时无法html代码高亮)。
同时我们还需要写不少for或者forEach去循环数组,再命令式的append,如果这段代码片段有一些复杂的交互,可能还需要通过事件代理绑定一堆方法。
如果在完成这类业务时,你也遇到过上述的问题,那么你就会发现Vue真是太coooooool了,let‘s vue!
新建一个Vue.js项目强烈推荐使用vue-cli来新建一个项目。
一开始你可能会认为用node.js和npm安装一大堆库,生成了一些你不太了解的目录和配置文件,一写代码还会跳出一堆eslint的提示。但是这绝对物有所值,因为这样的一个模板可以帮你更好的理解Vue.js组织文件的思路,并且当你适应之后,你会发现这些条条框框极大地加快了你的开发效率。
在这次的教程中,我们新建了一个名叫loadmore的项目,具体的新建项目流程可以参照官网教程的安装一节。
布局页面结构为了配合教程的逐步深入,我先从完成加载更多功能入手。为了和之后的分页保持一致,我的页面准备由两部分组成,一是信息列表,二是底部的一个加载更多的按钮,我将他们都放在App.vue这个根组件中。
在这个过程中,我们根据Vue的设计思想有了如下思路:
在信息列表中,我们会完成我们上文中提到的几个步骤,而这些步骤都只和信息列表本身有关,与Next按钮间唯一的联系就是Next点击后需要触发信息列表去获取,而这可以通过props传递。所以我们把列表及其自身业务逻辑、样式都放在List.vue这个组件中。
我们为按钮定义了一些基本的样式,但是我们用的css选择器就是一个.button类名,可能会和别的组件中的.button样式冲突,所以我们加入了一个scoped属性,让App.vue中的style样式只作用于这个组件内部。
注意:scoped并不会影响css的作用优先级,使用scoped不代表不会被外部样式表覆盖。
我们想引入一些基础样式,比如reset.css。如果在项目中使用了sass之类的语言,那么可以将对应的外部sass文件放在assets文件夹中,通过import引入。普通的css可以直接写在一个不加scoped属性的组件中,但是如果你确定这个样式表不会被频繁改动,那么也可以作为第三方静态资源引入index.html中。例如这个例子中,我在index.html中加入了:
效果:
完成List.vue
目前我们主要的业务逻辑都是围绕信息列表展开的,也就是我们创建的List.vue。
首先,我们需要获取目标数据,我选用了cnodejs.org社区的API作为例子进行编写。如果你也想用一个封装好的ajax库的话,应该这么做:
引入第三方JS库将目标JS库文件放在static文件夹中,例如我选择的是reqwest.js,然后在index.html先引入。
然后在build配置文件夹中,修改webpack.base.conf.js,export externals属性:
这样我们在我们的项目中,就可以随时加载第三方库了。
写个API接口在这个例子中,我们只需要调用文章列表这一个接口,但是实际项目中,可能你需要调用很多接口,而这些接口又会在多个组件中被用到。那么调用接口的逻辑四散在各个组件中肯定是不好的,想象一下对方的url发生了变化,你就得在无数个组件中一个个检查是否要修改。
所以我在src文件夹中新建了一个api文件夹,用于存放各类API接口。当前例子中,要获取的是新闻列表,所以新建一个news.js文件:
这样我们就拥有了一个获取新闻列表的API:getList。
编写组件我们用一个
-
作为新闻列表,内部的每一个
- 就是一条新闻,其中包括标题、时间和作者3个信息。
在data中,我们用一个名为list的数组来储存新闻列表的数据,一开始当然是空的。我们再在data中设置一个名为limit的值,用来控制每页加载多少条数据,作为参数传给getList这个API。
因此我们的template部分是这样的(加入了一些style美化样式):
之后我们显然需要使用getList来获取数据,不过先想想我们会在哪几个地方使用呢?首先,我们需要在组件开始渲染时自动获取一次列表,填充基础内容。其次,我们在每次点击APP.vue中的Next按钮时也需要获取新的列表。
所以我们在methods中定义一个get方法,成功获取到数据后,就把获取的数组拼接到当前list数组后,从而实现了加载更多。
沿着这个思路,再想想get方法需要的参数,一个是包含了page和limit两个属性的对象,另一个是回调函数。回调函数我们已经说过,只需要拼接数组即可,因此只剩下最后一个page参数还没设置。
在初始化的时候,page的值应该为1,默认是第一页内容。之后page的值只由Next按钮改变,所以我们让page通过props获取App.vue中传来的page值。
最后则是补充get方法触发的条件。一是在组件的生命周期函数created中调用this.get()获取初始内容,另一是在page值变化时对应获取,所以我们watch了page属性,当其变化时,调用this.get()。
最后List.vue的script长这样:
同时我们将App.vue中的修改为:
再为page在App.vue中添加一个初始值以及对应的方法next:
这样我们就已经完成了加载更多的功能。
因为之前我们的思路非常清晰,代码结构也很明了,所以改写起来会非常简单,只需要将List.vue中拼接数组改为赋值数组就可以了:
就这么简单的一行就完成了功能的改变,这就是Vue.js中核心的数据驱动视图的威力。当然,接下来我们还要做点更cooooool的。
添加功能因为分页替换了原来的数组,所以仅仅一个Next按钮不够用了,我们还需要一个Previous按钮返回上一页。同样的,也给Previous按钮绑定一个previous方法,除了用this.page--改变page的值以外,还需要对this.page === 1的边界条件进行一个判断。
同时为了方便知道我们当前的页数,在按钮中,加入{{ page }}显示页数。
transition动画编写和完善功能的过程中,已经充分体现了Vue.js清晰和便利的一面,接下来继续看看其它好用的功能,首先就是transition动画。
为了展示transition的威力,首先我找到了一个模仿的对象:lavalamp.js(Demo地址)。
在Demo中可以看到页面以一种非常优雅的动画过渡完成了切换内容的
以上是关于[DIV/CSS] Vue.js 开发实践:实现精巧的无限加载与分页功能的主要内容,如果未能解决你的问题,请参考以下文章