在element-ui的tabs组件中,我们发现每次切换页面,所有的子组件都会重新渲染一次。当子页面需要发送数据请求并且子页面过多时,这样会过多的占用网络资源。这里我们可以使用v-if来进行判断是否渲染该子页面。 不会如何在父页面载入子页面的可用看这一篇文章:在父页面引入子页面文件
v-if属于惰性加载,当值为false的时候,就不会加载。
这个办法是自己研究出来的一个方法,应该还有改善的空间, 本人在不断的优化代码,在发现了更简短的代码之后会在下面更新,已经更新到第三版。
需要使用的可直接看最后一个版本,如果想要学习交流的可用从上往下看。
1.在data中定义每个子组件相应的值,ture为加载,false为不加载。 2.在子组件中使用v-if来判断是否渲染当前页面 3.在函数中对子组件的值进行切换。
handleClick(tab) { switch (tab.name) { case "first": this.pageOne = true; this.pageTwo = false; this.pageThree = false; break; case "second": this.pageOne = false; this.pageTwo = true; this.pageThree = false; break; case "third": this.pageOne = false; this.pageTwo = false; this.pageThree = true; break; default: break; }使用switch来判断tab的name值,并且对不同情况做出不同的判断。 但是这对于子页面过多的情况来说实在是太麻烦了。所以研发出第二版~
1.这一次定义一个数组,将子页面的值都放在里面,用来判断该页面是否需要渲染
data() { return { activeName: "allOrder", pages: { allOrder: true,//第一个需要渲染的页面 unpaid: false, wangtingList: false, wangtingService: false, unCheck: false, finish: false, stayAway: false, }, }; },2.在子页面组件中使用v-if判断是否渲染
<el-tab-pane label="所有订单" name="allOrder"> <allOrder v-if="pages.allOrder"></allOrder> </el-tab-pane>3.定义切换组件时,需要渲染的界面,修改data内page中对应的数据的值。 handleClick(tab)是element-ui在原版代码中已经绑定好的函数,可以直接在method里定义,切换tabs的时候就会自动调用。 这一次我们使用了for循环来进行一个判断处理,代码会比第一版的switch要简洁一些。
handleClick(tab) { for (var i in this.pages) { console.log(i); if (tab.name != i) { this.pages[i] = false; // console.log(this.pages[i]); } else { this.pages[i] = true; } } },虽然在handleClick中我们进行了一些优化,但是在子组件代码上还是非常的冗余。七个子页面需要写七次,如果子页面再增加就会变得异常的繁琐。
<el-tabs v-model="activeName" @tab-click="handleClick"> <el-tab-pane label="所有订单" name="allOrder"> <allOrder v-if="pages.allOrder"></allOrder> </el-tab-pane> <el-tab-pane label="待支付" name="unpaid"> <unpaid v-if="pages.unpaid"></unpaid> </el-tab-pane> <el-tab-pane label="待派单" name="stayAway"> <stayAway v-if="pages.stayAway"></stayAway> </el-tab-pane> <el-tab-pane label="待接单" name="wangtingList"> <wangtingList v-if="pages.wangtingList"></wangtingList> </el-tab-pane> <el-tab-pane label="待服务" name="wangtingService"> <wangtingService v-if="pages.wangtingService"></wangtingService> </el-tab-pane> <el-tab-pane label="待确认" name="unCheck"> <unCheck v-if="pages.unCheck"></unCheck> </el-tab-pane> <el-tab-pane label="已完成" name="finish"> <finish v-if="pages.finish"></finish> </el-tab-pane> </el-tabs>1.在data中创建一个数组对象,在里面存放子组件名称以及展示在页面上的中文名。并定义一个变量存放当前需要渲染加载的页面。
data() { return { activeName: "allOrder",//第一个加载的页面 nowPage: "allOrder",//当前需要渲染的页面 pages: [ //所有子页面信息 { name: "allOrder", label: "所有订单", }, { name: "unpaid", label: "待支付", }, { name: "stayAway", label: "待派单", }, { name: "wangtingList", label: "待接单", }, { name: "wangtingService", label: "待服务", }, { name: "unCheck", label: "待确认", }, { name: "finish", label: "已完成", }, ], }; },2.在html中使用v-for循环生成子组件,将name和label赋值。 在循环生成的子组件中不能直接使用 <pages.name></pages.name>这样的写法来生成子页面,需要使用:is来加载对应的子页面,并用v-if来判断是否需要渲染当前子页面。
<el-tabs v-model="activeName" @tab-click="handleClick"> <el-tab-pane v-for="(pages, index) in pages" v-bind:key="index" :label="pages.label" :name="pages.name" > <!--循环生成子页面--> <components :is="pages.name" v-if="pages.name == nowPage"></components> </el-tab-pane> </el-tabs>3.在handleClick(tab)中修改需要加载的子页面
handleClick(tab) { this.nowPage = tab.name; },这样代码中html部分和函数部分就会变得非常的简短
整体代码
<template> <div style="padding: 20px" id="order"> <!-- @tab-click="handleClick"--> <el-tabs v-model="activeName" @tab-click="handleClick"> <el-tab-pane v-for="(pages, index) in pages" v-bind:key="index" :label="pages.label" :name="pages.name" > <components :is="pages.name" v-if="pages.name == nowPage"></components> </el-tab-pane> </el-tabs> </div> </template> <script> import allOrder from "./components/allOrder"; import unpaid from "./components/unpaid"; import wangtingList from "./components/wangtingList"; import wangtingService from "./components/wangtingService"; import unCheck from "./components/unCheck"; import finish from "./components/finish"; import stayAway from "./components/stayAway"; export default { data() { return { activeName: "allOrder", nowPage: "allOrder", pages: [ { name: "allOrder", label: "所有订单", }, { name: "unpaid", label: "待支付", }, { name: "stayAway", label: "待派单", }, { name: "wangtingList", label: "待接单", }, { name: "wangtingService", label: "待服务", }, { name: "unCheck", label: "待确认", }, { name: "finish", label: "已完成", }, ], }; }, methods: { //每次切换只渲染一个界面 handleClick(tab) { this.nowPage = tab.name; }, }, components: { allOrder, unpaid, wangtingList, wangtingService, unCheck, finish, stayAway, }, }; </script>效果:
总结: element-ui中的tabs每次点击时都会给所有页面重新渲染,为的是保证当子页面存在需要实时加载的情况下能保证数据的更新。
但是当子页面过多,每次切换都会把所有页面都加载,就会占用过多的网络资源。
v-if这个方法适用于非频繁切换的场景。在当前的使用中是非常合适的。
v-if判断是否加载,可以减轻服务器的压力,在需要时加载,但有更高的切换开销;如果在运行时条件很少改变,使用 v-if 进行一个选择性渲染会比较好。