浅学前端:Vue篇(二)

2023-11-12 17:31:45 浏览数 (1)

2. Vue 进阶

1) ElementUI

ElementUI是基于vue的一套组件库,前面讲述了如何自己去创建组件,但是自己创建组件成本太高了,所以我们一般都是采用一些第三方的比较成熟的组件库,ElementUI就是其中一中,使用之后可以大大减少我们的开发成本。

安装

代码语言:javascript复制
 npm install element-ui -S

引入组件

引入的方式有很多种,这里就介绍个最简单的,引入所有的组件

放在main.js中

代码语言:javascript复制
 import Element from 'element-ui' // 导入ElementUI组件
 import 'element-ui/lib/theme-chalk/index.css' // 导入他的一些样式
 ​
 // 之前我们自己使用组件的时候,我们是给options对象里的components去加组件
 // 但是ElementUI里的组件太多了,个数大于有几十种,如果一个个去加,太麻烦了,
 // 所以使用了另外一个手段vue的use方法,将Element对象传入,就会把所有Element的组件加入到内部去,以后在页面里就可以直接使用相关标签了
 Vue.use(Element)

测试,在自己的组件中使用 ElementUI 的组 件

代码语言:javascript复制
 <!-- ElementUI测试 -->
 <template>
     <div>
         <el-button>点我</el-button>
     </div>
 </template>
 <script>
     export default {}
 </script>

使用:

ElementUI用啥找啥就行,参考官网的例子。

1. 表格组件

具体属性见:https://element.eleme.cn/#/zh-CN/component/table

代码语言:javascript复制
 <template>
     <div>
         <!-- data属性:关联表格需要展示的数据 -->
         <el-table v-bind:data="students">
             <!-- lable属性:这个列的标题 -->
             <!-- prop属性:表格内部会遍历这个学生数组,那么学生对象的哪个属性需要显示在这一列上就使用到了prop -->
             <el-table-column label="编号" prop="ID"></el-table-column>
             <el-table-column label="姓名" prop="Name"></el-table-column>
             <el-table-column label="性别" prop="Sex"></el-table-column>
             <el-table-column label="年龄" prop="Age"></el-table-column>
         </el-table>
     </div>
 </template>
 <script>
 import axios from 'axios';
 export default {
     data: function () {
         return {
             "students": []
         };
     },
     mounted: async function () {
         const resp = await axios.get("/api/students")
         this.students = resp.data.data
     }
 };
 </script>

2. 分页组件

具体使用见:https://element.eleme.cn/#/zh-CN/component/pagination

分页常用的属性:

代码语言:javascript复制
 <template>
     <div>
         <!-- 分页常用属性:
             total属性:总条目数 
             page-size:每页显示条目个数,默认10条
             current-page:当前页数
             layout:控制分页条外观,
                 分页条可以看成由多个小的部分组成的
                 (比如:向上翻,向下翻,页码,跳转到第几页的数框,总记录数...)
                 这个layout就可以控制这些部分哪些显示,哪些不显示
                 默认是'prev, pager, next, jumper, ->, total'都显示
                 可选参数:sizes, prev, pager, next, jumper, ->, total, slot
             page-sizes:每页显示个数选择器的选项设置,默认:[10, 20, 30, 40, 50, 100]
         -->
         <el-pagination v-bind:total="50" v-bind:page-size="5" layout="prev, pager, next, sizes, ->, total"></el-pagination>
     </div>
 </template>
 <script>
 export default {};
 </script>

有人可能会好奇为什么有的属性加了v-bind,有的没有呢? 加了v-bind,就代表他的值来自于JavaScript,如果在option的data()返回的对象里找不到对应的绑定属性,就会将右侧当成表达式进行解析; 没有加:的,等号右边的值就是他的最终结果。 例子: :page-sizes="[5,10,15,20]"如果加了:会正常解析成数组,但是如果没加:,就会当做字符串,而不是解析成数组。

分页常用的事件:

示例:

代码语言:javascript复制
 <template>
     <div>
         <!-- data属性:关联表格需要展示的数据 -->
         <el-table v-bind:data="students">
             <!-- lable属性:这个列的标题 -->
             <!-- prop属性:表格内部会遍历这个学生数组,那么学生对象的哪个属性需要显示在这一列上就使用到了prop -->
             <el-table-column label="编号" prop="ID"></el-table-column>
             <el-table-column label="姓名" prop="Name"></el-table-column>
             <el-table-column label="性别" prop="Sex"></el-table-column>
             <el-table-column label="年龄" prop="Age"></el-table-column>
         </el-table>
         <!-- 分页常用事件:
             事件名称                说明              回调参数
             current-change  currentPage 改变时会触发     当前页
             size-change     pageSize 改变时会触发     每页条数
         -->
         <el-pagination 
                        v-bind:total="total" 
                        v-bind:page-size="queryPage.pageSize"
                        v-bind:current-page="queryPage.currentPage" 
                        v-on:current-change="currentChange"
                        v-on:size-change="sizeChange" 
                        v-bind:page-sizes="[2,3,5,7]"
             layout='prev, pager, next, sizes,jumper, ->, total'>
         </el-pagination>
     </div>
 </template>
 <script>
 import axios from 'axios';
 export default {
     data: function () {
         return {
             total: 0,
             students: [],
             queryPage: {
                 pageSize: 5, // 页大小
                 currentPage: 1, // 页码
             },
         };
     },
     methods: {
         currentChange(page) {
             this.queryPage.currentPage = page;
             this.queryStudents()
         },
         sizeChange(size) {
             this.queryPage.pageSize = size;
             this.queryStudents()
         },
         async queryStudents() {
             const resp = await axios.get("/api/students", {
                 params: this.queryPage,
             })
             this.students = resp.data.data.students;
             this.total = resp.data.data.total;
         },
     },
     mounted: function () {
         this.queryStudents()
     }
 };
 </script>
  • 三种情况都应该触发查询
    • mounted 组件挂载完成后
    • 页号变化时
    • 页大小变化时
  • 查询传参应该根据后台需求,灵活采用不同方式
    • 本例中因为是 get 请求,无法采用请求体,只能用 params 方式传参
  • 返回响应的格式也许会很复杂,需要掌握【根据返回的响应结构,获取数据】的能力
3. 分页搜索
  1. 按姓名模糊搜索
  2. 按性别精确搜索
  3. 按年龄范围查询
代码语言:javascript复制
 <template>
     <div>
         <!-- 输入框 -->
         <el-input placeholder="请输入姓名" v-model="queryDto.name"></el-input>
         <!-- 下拉列表 -->
         <el-select placeholder="请选择性别" v-model="queryDto.sex" clearable>
             <el-option value="男"></el-option>
             <el-option value="女"></el-option>
         </el-select>
         <!-- 下拉列表 -->
         <!-- label:展示给用户看的样子 -->
         <el-select placeholder="请选择年龄" v-model="queryDto.age" clearable>
             <el-option value="0,18" label="0到18岁"></el-option>
             <el-option value="19,30" label="19到30岁"></el-option>
             <el-option value="31,40" label="31到40岁"></el-option>
             <el-option value="41,120" label="41到120岁"></el-option>
         </el-select>
 ​
         <el-button type="primary" v-on:click="search()">搜索</el-button>
 ​
         <el-table v-bind:data="students">
             <el-table-column label="编号" prop="ID"></el-table-column>
             <el-table-column label="姓名" prop="Name"></el-table-column>
             <el-table-column label="性别" prop="Sex"></el-table-column>
             <el-table-column label="年龄" prop="Age"></el-table-column>
         </el-table>
         <el-pagination v-bind:total="total" v-bind:page-size="queryDto.pageSize"
             v-bind:current-page="queryDto.currentPage" v-on:current-change="currentChange" v-on:size-change="sizeChange"
             v-bind:page-sizes="[2,3,5,7]" layout='prev, pager, next, sizes,jumper, ->, total'>
         </el-pagination>
     </div>
 </template>
 <script>
 import axios from 'axios';
 export default {
     data: function () {
         return {
             total: 0,
             students: [],
             queryDto: {
                 pageSize: 5, // 页大小
                 currentPage: 1, // 页码
                 name: '',
                 sex: '',
                 age: ''
             },
         };
     },
     methods: {
         currentChange(page) {
             this.queryDto.currentPage = page;
             this.queryStudents()
         },
         sizeChange(size) {
             this.queryDto.pageSize = size;
             this.queryStudents()
         },
         async queryStudents() {
             const resp = await axios.get("/api/students", {
                 params: this.queryDto,
             })
             this.students = resp.data.data.students;
             this.total = resp.data.data.total;
         },
         search() {
             this.queryStudents()
         }
     },
     mounted: function () {
         this.queryStudents()
     },
 };
 </script>
4. Cascader 级联选择器

级联选择器中选项的数据结构为:

代码语言:javascript复制
 <!-- 多级菜单 -->
 <template>
     <div>
         <el-cascader v-bind:options="ops"></el-cascader>
     </div>
 </template>
 <script>
     export default {
         data:function(){
             return {
                 // 多级菜单的数据
                 ops:[
                     {value:100,label:'主页',children:[
                         {value:101,label:'菜单1',children:[
                             {value:105,label:'子项1'},
                             {value:106,label:'子项2'},
                         ]},
                         { value: 102, label: '菜单2', children: [
                             {value:107,label:'子项3'},
                             {value:108,label:'子项4'},
                             {value:109,label:'子项5'},
                         ]},
                         { value: 103, label: '菜单3', children: [
                             {value:110,label:'子项6'},
                             {value:111,label:'子项7'},
                         ] },
                         {value:104,label:'菜单4'},
                     ]}
                 ],
             };
         },
     };
 </script>

上面将选项数据写死在了javaScipt里,更合理的做法应该来自后端服务器:

数据准备:

代码语言:javascript复制
 CREATE TABLE `menu`(
     id INT,
     name VARCHAR(10),
     icon VARCHAR(30),
     path VARCHAR(30),
     pid INT,
     PRIMARY KEY (id)
 ) COMMENT '菜单表';
 ​
 INSERT INTO menu (id, name, icon, path, pid) values
     (100,'主页','el-icon-menu','/',0),
         (101,'菜单1','el-icon-menu','/menu1',100),
             (105,'子项1','el-icon-menu','/menu1/c1',101),
             (106,'子项2','el-icon-menu','/menu1/c2',101),
         (102,'菜单2','el-icon-menu','/menu2',100),
             (107,'子项3','el-icon-menu','/menu2/c3',102),
             (108,'子项4','el-icon-menu','/menu2/c4',102),
             (109,'子项5','el-icon-menu','/menu2/c5',102),
         (103,'菜单3','el-icon-menu','/menu3',100),
             (110,'子项6','el-icon-menu','/menu3/c6',103),
             (111,'子项7','el-icon-menu','/menu3/c7',103),
         (104,'菜单4','el-icon-menu','/menu4',100);

后端代码自己写,表里的数据是一维的,没有层级关系的,后端的人可以直接返给你有层级的关系的数据,但是如果他们不想写,而是给你返回一维的这种数组,那么前端就需要自己将这个一维的数组转换成这种树状的数据(这也是个基本功)。

下面的例子是将后端返回的一维数组【树化】

代码语言:javascript复制
 <!-- 多级菜单 -->
 <template>
     <div>
         <el-cascader v-bind:options="ops"></el-cascader>
     </div>
 </template>
 <script>
 import axios from 'axios';
 export default {
     data: function () {
         return {
             // 多级菜单的数据
             // cascade级联选择器只需要最顶层的对象,就会从children里遍历子对象(所有只需要将最顶层的对象给他就行)。
             ops: [],
         };
     },
     mounted: async function () {
         const resp = await axios.get("/api/menu");
         const menus = resp.data.data;
         // 1. 将所有数据存入map集合(为了接下来查找效率)
         const map = new Map(); // set get
         for (const { Id, Name, Pid } of menus) {
             map.set(Id, { value: Id, label: Name, pid: Pid });
         }
 ​
         // 2. 建立父子关系
         const top = [];
         for (const obj of map.values()) {
             if (obj.pid !== 0) {
                 const parent = map.get(obj.pid)
                 // 如果父节点还没定义子数组,就创建一个空的数组
                 if (parent.children === undefined) {
                     parent.children = [];
                 }
                 parent.children.push(obj);
             } else {
                 // 3. 找到顶层对象,本例中顶层对象只有一个,但是实际上可能不止,所以使用数组
                 // cascade级联选择器只需要最顶层的对象,就会从children里遍历子对象(所有只需要将最顶层的对象给他就行)。
                 // 这个时候的top顶层对象是与所有子对象建立完联系了的
                 top.push(obj);
             }
         }
         this.ops = top;
     },
 };
 </script>

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞