ElementUI


# ElementUI 的使用

dj vue-element-demo
每个组件的方法在文档中查看 (https://element.eleme.cn/#/zh-CN/component/installation)
element-ui 的使用 基于 @vue-cli 3+

# 安装

命令行输入:vue add element
vue ui: 选择 element 插件安装
选择 import on damand (按需加载方式)
安装完之后,如果页面没有效果,需要重新启动一下

# 简单使用

Message 消息提示不需要 use,只需要 Vue.prototype.$message = Message,这样才可以使用 $message 方法

  • App.vue

    <template>
      <div>
        <h1>hello element-UI</h1>
        <!-- element-ui 内的组件可以分为两种 -->
        <!-- 1.组件形式的 -->
        <!-- element-ui 组件的事件绑定如果没有文档特殊提示的话
        直接像使用原生元素一样绑定事件,style 也是一样 -->
        <el-button
          type="danger"
          round
          :loading="isLoading"
          :style="{ width: '200px' }"
          @click="isLoading = true"
          >按钮</el-button
        >
        <el-date-picker
          v-model="date"
          :editable="false"
          @change="change"
          value-format="yyyy-MM-dd"
        />
        <el-switch
          v-model="open"
          :width="50"
          inactive-icon-class="img"
          active-icon-class="img"
          @change="switchChange"
        />
    
        <br />
        <br />
        <!-- 2.方法类型 -->
        <el-button @click="showMessage">测试 Message 方法</el-button>
      </div>
    </template>
    
    <script>
      // element-ui 的使用 基于 @vue-cli 3+
    
      // element-ui 里面的方法哪个组件想用直接导入使用
      // 也可以制作成 vue 全局的方法 直接使用 this 访问,需要使用 Vue.prototype 设置成全局方法
      // import { Message } from "element-ui";
      export default {
        name: "App",
        data() {
          return {
            isLoading: false,
            date: "",
            open: true,
          };
        },
        methods: {
          change(a) {
            console.log(a); //拿到的是选择的日期
          },
          switchChange(e) {
            console.log(e); //true和false
          },
          showMessage() {
            // Message("这是一条提示信息");
            this.$message("这是一条提示信息");
          },
        },
      };
    </script>
    
    <style>
      .img {
        width: 20px;
        height: 20px;
        background-size: 100%;
        background-image: url("./assets/logo.png");
      }
    </style>
  • element.js

    import Vue from "vue";
    import { Button, DatePicker, Switch, Message } from "element-ui";
    
    // 将 Button 组件注册成全局组件
    Vue.use(Button);
    Vue.use(DatePicker);
    Vue.use(Switch);
    
    // 将 Message 制作成全局方法
    // $message 可以随便命名
    Vue.prototype.$message = Message;

# 导航菜单 (elementUI 中的案例)

  • MenuDemo.vue, 自己生成标签

    <template>
      <div>
        <el-menu class="el-menu-vertical-demo">
          <!-- v-for 是生成多个同样的标签或组件 -->
          <template v-for="(item, index) in menu">
            <el-submenu
              :key="item.id"
              :index="(index + 1) | toString"
              v-if="item.children && item.children.length"
            >
              <template #title>
                <span>{{ item.title }}</span>
              </template>
              <!-- 生成嵌套子菜单 -->
              <el-menu-item
                v-for="(ele, ind) in item.children"
                :key="ele.id"
                :index="`${(index + 1) | toString}-${(ind + 1) | toString}`"
              >
                <template #title>
                  <span> {{ ele.title }}</span>
                </template>
              </el-menu-item>
            </el-submenu>
    
            <el-menu-item :key="item.id" :index="(index + 1) | toString" v-else>
              <template #title> <span>{{ item.title }}</span></template>
            </el-menu-item>
          </template>
        </el-menu>
      </div>
    </template>
    
    <script>
      export default {
        filters: {
          // 过滤器 传参 | 过滤器名称
          toString: function (value) {
            return value.toString();
          },
        },
        data() {
          return {
            // 后台提供的菜单数组
            menu: [
              {
                id: 1,
                title: "菜单1",
                children: [
                  {
                    id: 3,
                    title: "菜单1-1",
                  },
                  {
                    id: 4,
                    title: "菜单1-2",
                  },
                ],
              },
              {
                id: 2,
                title: "菜单2",
              },
              {
                id: 5,
                title: "菜单3",
              },
            ],
          };
        },
      };
    </script>

# Tree 树形

  • TreeDemo.vue

    <template>
      <div>
        <h2>Tree组件</h2>
    
        <el-input
          placeholder="输入关键字进行过滤"
          v-model="filterText"
        ></el-input>
        <el-tree
          ref="tree"
          :data="data"
          :props="defaultProps"
          @node-click="handleNodeClick"
          show-checkbox
          @check-change="checkChange"
          default-expand-all
          :filter-node-method="filterNode"
        >
          <!-- 借助作用域插槽 自定义树的节点内容 -->
          <!-- 默认的插槽就是节点内容 -->
          <!-- 在 tree 组件内已经向插槽传递了数据,
          只需要在使用tree组件的时候,在传递的插槽中接收即可 -->
          <!-- 插槽传递的数据有两个
           node:当前节点对象 
          data:树的初始数据(就是底下data中的整个data数组) -->
          <template v-slot:default="{ node }">
            <span class="custom-tree-node">
              <span
                v-html="$options.filters.filterNodeStr(node.label,filterText)"
              ></span>
              <span>
                <el-button type="text" size="mini">Append</el-button>
                <el-button type="text" size="mini">Delete</el-button>
              </span>
            </span>
          </template>
        </el-tree>
      </div>
    </template>
    
    <script>
      export default {
        name: "TreeDemo",
        data() {
          return {
            data: [
              {
                label: "一级 1",
                children: [
                  {
                    label: "二级 1-1",
                    children: [
                      {
                        label: "三级 1-1-1",
                      },
                    ],
                  },
                ],
              },
              {
                label: "一级 2",
                children: [
                  {
                    label: "二级 2-1",
                    children: [
                      {
                        label: "三级 2-1-1",
                      },
                    ],
                  },
                  {
                    label: "二级 2-2",
                    children: [
                      {
                        label: "三级 2-2-1",
                      },
                    ],
                  },
                ],
              },
              {
                label: "一级 3",
                children: [
                  {
                    label: "二级 3-1",
                    children: [
                      {
                        label: "三级 3-1-1",
                      },
                    ],
                  },
                  {
                    label: "二级 3-2",
                    children: [
                      {
                        label: "三级 3-2-1",
                      },
                    ],
                  },
                ],
              },
            ],
            defaultProps: {
              children: "children", // 节点子树的属性名
              label: "label", // 指定的是节点标签的属性名
            },
            filterText: "",
          };
        },
        filters: {
          filterNodeStr(label, filterText) {
            const isHasKeyWord = label.includes(filterText);
            // 返回的字符串会使用 v-html 加载到 span 标签内
            if (filterText === "" || !isHasKeyWord) return label;
            const startIndex = label.indexOf(filterText);
            // 这里最外层的span省略了,因为上边用了span标签
            return `<span>${label.slice(0, startIndex)}</span>
            <span class='key-word'>${filterText}</span>
            <span>${label.slice(startIndex + filterText.length)}</span>`;
          },
        },
        watch: {
          // 监听 filterText 的变化
          filterText(val) {
            // element-ui 内有的组件自带一些方法,使用对应的组件可以直接调用
            // 通过 ref 获取组件
            // ref 使用在组件身上的话获取的是组件本身
            // ref 使用在非组件身上的话获取的是真实 dom 元素
            console.log(this.$refs.tree);
            // filter 是 tree 组件自带的筛选节点方法
            this.$refs.tree.filter(val);
            // 这个监听实现的是一旦 filterText 发生了改变就使用 tree 组件自带的 fitler 方法,
            // 执行 tree 组件接收的filter-node-method prop,
            // 并将 filterText 传递给该方法当作第一个参数
            // filter-node-method tree 组件有多少个节点,执行多少次
          },
        },
        methods: {
          handleNodeClick() {
            // 默认接收三个参数 obj, node, nodeCommonent
            // console.log(obj);
            // console.log(node);
            // console.log(nodeCommonent);
          },
          checkChange() {
            // console.log("复选框发生了改变");
          },
          filterNode(value, data) {
            // console.log(value);
            // 该函数会默认接收两个参数 第一个是 tree 组件的filter方法传递的参数
            // 第二个是当前节点的数据内容data(data中的data数组)
            // tree 组件有多少个节点,该方法执行多少次,每次需要设置返回值来控制节点的出现和消失
            // console.log(data);
            if (!value) return true;
            return data.label.indexOf(value) !== -1;
          },
        },
      };
    </script>
    
    <style>
      .custom-tree-node {
        display: flex;
        align-items: center;
      }
      .key-word {
        color: orange;
      }
    </style>

# 表格

  • 案例 1

    • TableDemo.vue (data 中一共 100 条数据,这里省略了 95 个)

      <template>
        <div>
          <h2>TableDemo</h2>
          <el-table :data="showTableData" border style="width: 100%">
            <el-table-column
              prop="id"
              label="序号"
              width="180"
              align="center"
            ></el-table-column>
            <el-table-column prop="title" label="标题"></el-table-column>
      
            <el-table-column label="重要性" width="180" align="center">
              <!-- table-column 的作用域插槽,slotProps是组件内部使用插槽的时候传递的数据,slotProps.row 就是对应的表格内的某一项 -->
              <template v-slot="{row}">
                <el-rate
                  v-model="row.important"
                  disabled
                  :max="row.important"
                  :colors="['#000']"
                ></el-rate>
              </template>
            </el-table-column>
      
            <el-table-column label="操作" width="180" align="center">
              <el-button type="primary" size="mini">编辑</el-button>
              <el-button type="danger" size="mini">删除</el-button>
            </el-table-column>
          </el-table>
      
          <!-- <el-pagination
            :current-page="currentPage"
            :page-size="10"
            background
            layout="prev, pager, next"
            :total="tableData.length"
            @current-change="pageChange"
          ></el-pagination>-->
      
          <el-pagination
            :current-page.sync="currentPage"
            :page-size="10"
            background
            layout="prev, pager, next"
            :total="tableData.length"
          ></el-pagination>
        </div>
      </template>
      
      <script>
        export default {
          name: "TableDemo",
          data() {
            return {
              tableData: [
                {
                  important: 2,
                  userId: 1,
                  id: 1,
                  title:
                    "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
                  body:
                    "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
                },
                {
                  important: 4,
                  userId: 1,
                  id: 2,
                  title: "qui est esse",
                  body:
                    "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
                },
                {
                  important: 5,
                  userId: 1,
                  id: 3,
                  title:
                    "ea molestias quasi exercitationem repellat qui ipsa sit aut",
                  body:
                    "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
                },
                {
                  important: 3,
                  userId: 1,
                  id: 4,
                  title: "eum et est occaecati",
                  body:
                    "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit",
                },
                {
                  important: 2,
                  userId: 1,
                  id: 5,
                  title: "nesciunt quas odio",
                  body:
                    "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque",
                },
              ],
              currentPage: 1,
            };
          },
          computed: {
            showTableData() {
              return this.tableData.slice(
                (this.currentPage - 1) * 10,
                this.currentPage * 10
              );
            },
          },
          methods: {
            /* pageChange(page) {
            console.log(111);
            this.currentPage = page;
          } */
          },
        };
      </script>
  • 案例 2 在服务器中加载数据

    • 项目下新建的 data 文件夹 中的 data.json 文件 (一共 100 条数据,这里省略了 95 个)
      (要在 data.json 文件打开命令行工具输入 json-server --watch data.json -p 3008)

      {
        "posts": [
          {
            "important": 3,
            "userId": 1,
            "id": 1,
            "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
            "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
          },
          {
            "important": 2,
            "userId": 1,
            "id": 2,
            "title": "qui est esse",
            "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
          },
          {
            "important": 4,
            "userId": 1,
            "id": 3,
            "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
            "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
          },
          {
            "important": 2,
            "userId": 1,
            "id": 4,
            "title": "eum et est occaecati",
            "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
          },
          {
            "important": 2,
            "userId": 1,
            "id": 5,
            "title": "nesciunt quas odio",
            "body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
          }
        ]
      }
    • TableDemo.vue

      <template>
        <div>
          <h2>TableDemo</h2>
          <div v-if="tableData.length">
            <el-table :data="tableData" border style="width: 100%">
              <el-table-column
                prop="id"
                label="序号"
                width="180"
                align="center"
              ></el-table-column>
              <el-table-column prop="title" label="标题"></el-table-column>
      
              <el-table-column label="重要性" width="180" align="center">
                <!-- table-column 的作用域插槽,slotProps是组件内部使用插槽的时候传递的数据
                ,slotProps.row 就是对应的表格内的某一项 -->
                <template v-slot="{ row }">
                  <el-rate
                    v-model="row.important"
                    disabled
                    :max="row.important"
                    :colors="['#000']"
                  ></el-rate>
                </template>
              </el-table-column>
      
              <el-table-column label="操作" width="180" align="center">
                <el-button type="primary" size="mini">编辑</el-button>
                <el-popconfirm title="确定删除这一条数据吗" @confirm="delPost()">
                  <template #reference>
                    <el-button type="danger" size="mini">删除</el-button>
                  </template>
                </el-popconfirm>
              </el-table-column>
            </el-table>
      
            <!-- <el-pagination
              :current-page.sync="currentPage"
              :page-size="10"
              background
              layout="prev, pager, next"
              :total="tableData.length"
            ></el-pagination> -->
            <!-- 对应1,2 created -->
      
            <!--  <el-pagination
              :current-page="currentPage"
              :page-size="10"
              background
              layout="prev, pager, next"
              :total="100"
              @current-change="pageChange"
            ></el-pagination> -->
            <!-- 对应的方法,这里pageChange没有被注释 -->
      
            <el-pagination
              :current-page.sync="currentPage"
              :page-size="10"
              background
              layout="prev, pager, next"
              :total="total"
            ></el-pagination>
          </div>
          <div v-else>我是 gif图,我在努力加载</div>
        </div>
      </template>
      
      <script>
        // 下载了 axios (npm i axios) 在项目文件夹中执行
        import axios from "axios";
        export default {
          name: "TableDemo",
          data() {
            return {
              tableData: [],
              currentPage: 5,
              total: 100,
            };
          },
          /* created() {
            axios
              .get("http://localhost:3008/posts?_page=1&_limit=10")
              .then((res) => {
                console.log(res.data);
              });
          }, */
          /* async created() {
            const res = await axios.get(
                `http://localhost:3008/posts?_page=${this.currentPage}&_limit=10`
            );
            console.log(res.data);
            this.tableData = res.data;
            // 这里只会一进来展示第几页,点击页数的时候不会修改,所以需要一个methods方法pageChange
            // 也可以使用 监听器 watch 监听 currentPage
          }, */
          /* created() {
            this.getPosts(this.currentPage);
          }, */
          watch: {
            currentPage: {
              handler(newVal) {
                // newVal 新的一页
                this.getPosts(newVal);
              },
              immediate: true,
            },
          },
          computed: {
            /* showTableData() {
            return this.tableData.slice(
              (this.currentPage - 1) * 10,
              this.currentPage * 10
            );f
          }, */
          },
          methods: {
            async getPosts(page) {
              const res = await axios.get(
                `http://localhost:3008/posts?_page=${page}&_limit=10`
              );
              this.tableData = res.data;
            },
            /* pageChange(page) {
              this.currentPage = page;
              this.getPosts(page);
            }, */
          },
        };
      </script>
  • 案例 3 过滤,编辑,删除,添加等功能

    • TableDemo.vue

      <template>
        <div>
          <h2>TableDemo</h2>
      
          <!-- 对话框 -->
          <el-dialog
            title="添加文章"
            :visible.sync="showDialog"
            :close-on-click-modal="false"
            class="table"
          >
            <el-form :model="post" ref="elFormComponent">
              <!-- rules 是规则数组,里面的每一项都是一个规则 -->
              <el-form-item
                prop="title"
                label="标题"
                :rules="[
                      { required: true, message: '请输入标题', trigger: 'blur' }
                    ]"
              >
                <el-input v-model="post.title"></el-input>
              </el-form-item>
              <el-form-item
                label="作者ID"
                prop="userId"
                :rules="[
                      { required: true, message: '请输入作者 id', trigger: 'blur' }
                    ]"
              >
                <el-input v-model.number="post.userId"></el-input>
              </el-form-item>
              <el-form-item label="重要性">
                <el-rate v-model="post.important"></el-rate>
              </el-form-item>
              <el-form-item
                label="内容"
                prop="body"
                :rules="[
                      { required: true, validator:validateContent, trigger: 'blur' }
                    ]"
              >
                <el-input v-model="post.body" type="textarea"></el-input>
              </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
              <el-button @click="closeDialog">取 消</el-button>
              <el-button type="primary" @click="dialogConfirmBtnClick"
                >确 定</el-button
              >
            </div>
          </el-dialog>
      
          <!-- 表格 -->
          <!-- <div v-if="tableData.length"> -->
          <div>
            <el-input
              style="width:150px"
              v-model="searchTxt"
              placeholder="标题"
            ></el-input>
            <el-button type="primary" icon="el-icon-search" @click="search"
              >搜索</el-button
            >
            <el-button type="primary" @click="openDialog">添加</el-button>
      
            <el-table
              :data="tableData"
              border
              style="width: 100%"
              v-loading="loading"
            >
              <el-table-column
                prop="id"
                label="序号"
                width="180"
                align="center"
                sortable
              ></el-table-column>
              <el-table-column
                prop="title"
                label="标题"
                sortable
              ></el-table-column>
      
              <el-table-column label="重要性" width="180" align="center" sortable>
                <!-- table-column 的作用域插槽,slotProps是组件内部使用插槽的时候传递的数据,slotProps.row 就是对应的表格内的某一项 -->
                <template v-slot="{ row }">
                  <el-rate
                    v-model="row.important"
                    disabled
                    :max="row.important"
                    :colors="['#000']"
                  ></el-rate>
                </template>
              </el-table-column>
      
              <el-table-column label="操作" width="180" align="center" sortable>
                <!-- 点击删除的确认按钮,需要传递 id 作为参数进行删除操作,所以需要使用作用域插槽获取id -->
                <template v-slot="{ row }">
                  <el-button type="primary" size="mini" @click="edit(row.id)"
                    >编辑</el-button
                  >
                  <!-- 点击删除的确认按钮需要传递 id 作为参数,进行删除操作,所以需要使用 -->
                  <el-popconfirm
                    title="确定删除这一条数据吗"
                    @confirm="delPost(row.id)"
                  >
                    <template #reference>
                      <el-button type="danger" size="mini">删除</el-button>
                    </template>
                  </el-popconfirm>
                </template>
              </el-table-column>
            </el-table>
      
            <!-- <el-pagination
              :current-page="currentPage"
              :page-size="10"
              background
              layout="prev, pager, next"
              :total="tableData.length"
              @current-change="pageChange"
              ></el-pagination>-->
            <el-pagination
              :current-page.sync="currentPage"
              :page-size="10"
              background
              layout="prev, pager, next"
              :total="total"
            ></el-pagination>
          </div>
          <!-- <div v-else>我是 gif图,我在努力加载</div> -->
        </div>
      </template>
      
      <script>
        import axios from "axios";
        export default {
          name: "TableDemo",
          data() {
            return {
              tableData: [],
              currentPage: 1,
              total: 100,
              showDialog: false,
              post: { title: "", important: null, body: "", userId: null },
              // 是否处于编辑状态,点击编辑的时候修改
              editPostId: null,
              searchTxt: "",
              oldSearchTxt: "",
              isSearching: false,
              loading: false,
              // filterImportant:2
            };
          },
          /* created() {
            axios.get("http://localhost:3008/posts?_page=1&_limit=10").then((res) => {
              console.log(res.data);
            });
          }, */
          /* created() {
            //  const res = await axios.get(
            //   `http://localhost:3008/posts?_page=${this.currentPage}&_limit=10`
            // );
            // // console.log(res.data);
            // this.tableData = res.data;
            this.getPosts(this.currentPage);
          }, */
          watch: {
            currentPage: {
              /* handler(newVal) {
                // 当点击分页器的时候,搜索过了和没搜索传递的 参数是有区别的
                console.log(newVal);
                const option = this.isSearching
                  ? { page: newVal.page, title: newVal.title }
                  : { page: newVal.page };
                this.getPosts(option);
              },
              immediate: true,
              deep:true */
              handler(newVal) {
                // 当点击分页器的时候,搜索过了和没搜索传递的 参数是有区别的
                // console.log(newVal);
                const option = this.isSearching
                  ? { page: newVal, title: this.searchTxt }
                  : { page: newVal };
                this.getPosts(option);
      
                // 参数很多
                /* let option = { page: newVal };
                if (this.isSearching) {
                  if (title) {
                    option.title = this.searchTxt;
                  }
                  if (important) {
                    option.important = this.filterImportant;
                  }
                } */
              },
              immediate: true,
            },
          },
          computed: {
            /* showTableData() {
              return this.tableData.slice(
                (this.currentPage - 1) * 10,
                this.currentPage * 10
              );
            }, */
          },
          methods: {
            // 获取的内容(请求数据的方法)
            async getPosts(option) {
              this.loading = true;
              const { page = 1, title } = option;
              const baseUrl = `http://localhost:3008/posts?_page=${page}&_limit=10`;
              const queryUrl = title ? `&title_like=${title}` : ``;
              // 参数很多时
              /*  const importantUrl = filterImportant
                ? `&important=${this.filterImportant}`
                : ``; */
              const res = await axios.get(baseUrl + queryUrl);
              setTimeout(() => {
                this.tableData = res.data;
                this.loading = false;
              }, 500);
            },
            // 查找函数
            search() {
              const { searchTxt, oldSearchTxt } = this;
              if (oldSearchTxt !== searchTxt) {
                // 搜索结果默认展示第一页,分页器展示也是第一页
                this.currentPage = 1;
                this.oldSearchTxt = searchTxt;
                this.isSearching = true;
                this.getPosts({ title: searchTxt });
              } else if (searchTxt === "") {
                // 空的时候点搜索重置
                console.log("重置");
                this.getPosts({ page: 1 });
                this.isSearching = false;
                this.currentPage = 1;
                this.oldSearchTxt = "";
              }
            },
            /* pageChange(page) {
              this.currentPage = page;
              this.getPosts(page);
            }, */
            async delPost(id) {
              // console.log(id);
              await axios.delete(`http://localhost:3008/posts/${id}`);
              // json-server 删除的返回值就是空对象 没啥用
              // 删了网上的数据需要更新本地数据
              this.tableData = this.tableData.filter((post) => post.id !== id);
              this.total--;
              // 全局的 notify 方法
              this.$notify({
                title: "成功",
                message: "删除成功",
                // icon
                type: "success",
              });
            },
            // 文章内容的自定义校验规则
            validateContent(rule, value, callback) {
              if (value === "") {
                callback(new Error("请输入内容"));
              } else if (value.length < 10) {
                // 包含敏感词汇,长度不够等等
                callback(new Error("字数不够"));
              } else if (value.includes("yyds")) {
                callback(new Error("包含敏感词汇"));
              } else {
                callback();
              }
            },
            openDialog() {
              this.showDialog = true;
            },
            closeDialog() {
              this.showDialog = false;
              this.editPostId = null;
              this.post = {
                title: "",
                important: null,
                body: "",
                userId: null,
              };
            },
            // 对话框确定按钮的单击事件
            dialogConfirmBtnClick() {
              // this.$refs.elFormComponent.validate 表单整体的校验事件
              this.$refs.elFormComponent.validate((result) => {
                if (result) {
                  const { editPostId } = this;
                  editPostId ? this.editPost(editPostId) : this.addPost();
                }
              });
            },
            async addPost() {
              const res = await axios.post(
                `http://localhost:3008/posts`,
                this.post
              );
              // console.log(res.data);
              this.tableData.unshift(res.data);
              this.total++;
              this.closeDialog();
              // 添加成功需要清空,防止再次添加出现默认值
              this.post = {
                title: "",
                important: null,
                body: "",
                userId: null,
              };
              this.$notify({
                title: "成功",
                message: "添加成功",
                // icon
                type: "success",
              });
              // console.log(this.post);
              /*  this.$refs.elFormComponent.validate(async result => {
                if (result) {
                  const res = await axios.post(
                    `http://localhost:3008/posts`,
                    this.post
                  );
                  // console.log(res.data);
                  this.tableData.unshift(res.data);
                  this.total++;
                  this.closeDialog();
                  // 添加成功需要清空,防止再次添加出现默认值
                  this.post = {
                    title: "",
                    important: null,
                    body: "",
                    userId: null
                  };
                  this.$notify({
                    title: "成功",
                    message: "添加成功",
                    // icon
                    type: "success"
                  });
                }
              }); */
            },
            // 通过 id 获取对应的文章信息
            getPostById(id) {
              return this.tableData.find((post) => post.id === id);
            },
            // 点击编辑弹窗事件
            edit(id) {
              this.openDialog();
              // 需要做拷贝,不拷贝的话删除id 就相当于删除了原始 data 数据内的 id
              const editPost = { ...this.getPostById(id) };
              // 删除对象的id属性
              delete editPost.id;
              this.post = editPost;
      
              // 1.点击弹窗确定的时候判断什么时候添加还是编辑
              // 2.点击确定的时候,根据id发请求
              this.editPostId = id;
            },
            // 修改函数
            async editPost(id) {
              // 将修改的数据传回服务器
              // patch 局部更新
              const res = await axios.patch(
                `http://localhost:3008/posts/${id}`,
                this.post
              );
              // console.log(res.data);
      
              // 将 data 内的对应的 id 那条数据替换成请求的结果
              const ind = this.tableData.findIndex((post) => post.id === id);
              this.tableData.splice(ind, 1, res.data);
      
              this.closeDialog();
      
              // 添加成功需要清空,防止再次添加出现默认值
              this.editPostId = null;
              this.post = {
                title: "",
                important: null,
                body: "",
                userId: null,
              };
              this.$notify({
                title: "成功",
                message: "编辑成功",
                type: "success",
              });
            },
          },
        };
      </script>
      
      <style>
        /* 有的ui库可能加上scoped之后,你直接使用 ui 库内的class修改样式的时候会不起作用 */
        .table .el-rate {
          display: flex;
          height: 40px;
          align-items: center;
        }
      </style>

# InfiniteScroll.vue 文件

<template>
  <!-- 滚动条到底了 load 函数触发,但是加载有延迟,延迟时间过长,触底的load函数又会触发,导致 load 函数触发多次 -->
  <!-- 使用 infinite-scroll-disabled 禁用加载,当加载的时候直接禁用 -->
  <ul
    class="infinite-list"
    :infinite-scroll-disabled="disabled"
    v-infinite-scroll="load"
    infinite-scroll-distance="5"
    style="overflow:auto"
  >
    >
    <!--  infinite-scroll-distance="5" 距离底部还是5px的时候就触发 -->
    <li v-for="i in count" :key="i" class="infinite-list-item">{{ i }}</li>
    <li v-if="loading">加载中……</li>
    <li v-if="noMore">没有更多了</li>
  </ul>
</template>

<script>
  export default {
    name: "InfiniteScroll",
    data() {
      return {
        count: 10,
        loading: false,
      };
    },
    computed: {
      noMore() {
        return this.count >= 30;
      },
      disabled() {
        return this.loading || this.onMore;
      },
    },
    methods: {
      // load 函数设置给了 v-infinite-scroll 指令,当滚动条触底的时候会触发该函数
      // 当设定指令的元素设置了滚动条但滚动条还没出现的时候 load 会自动触发,直到滚动条出现并且不触底
      load() {
        console.log("加2");
        this.loading = true;
        setTimeout(() => {
          this.loading = false;
          this.count += 2;
        }, 500);
      },
    },
  };
</script>

<style>
  .infinite-list {
    list-style: none;
    padding-left: 0;
    width: 400px;
    margin: 0 auto;
    height: 500px;
  }
  .infinite-list-item {
    height: 50px;
    background-color: #e8f3fe;
    margin: 10px;
    color: #7dbcfc;
  }
</style>

# Item.vue 文件

<template>
  <div>
    <!-- 我是列表项 -->
    <slot :x="qianzhui" />
  </div>
</template>

<script>
  export default {
    name: "Item",
    data() {
      return {
        qianzhui: "哈哈哈",
      };
    },
  };
</script>

# JsonServerDemo.vue 文件

<template>
  <div>
    <h2>JsonServerDemo</h2>
    <el-button type="primary" @click="edit">编辑第一条评论</el-button>
  </div>
</template>

<script>
  import axios from "axios";
  export default {
    name: "JsonServerDemo",
    // put 替换  patch 局部更新(一般改一个的时候用这个)
    methods: {
      edit() {
        axios
          .patch("http://localhost:3008/comments/1", { text: "yyds" })
          .then((res) => {
            console.log(res, "编辑成功");
          });
      },
    },
  };
</script>

# data.json 文件 (一共一百条数据,这里省略了 95 条)

{
  "comments": [
    {
      "id": 1,
      "text": "yyds",
      "author": "小张"
    },
    {
      "id": 2,
      "text": "888",
      "author": "小赵"
    }
  ],
  "posts": [
    {
      "important": 2,
      "userId": 1,
      "id": 2,
      "title": "qui est esse",
      "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
    },
    {
      "important": 4,
      "userId": 1,
      "id": 3,
      "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
      "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
    },
    {
      "important": 2,
      "userId": 1,
      "id": 4,
      "title": "eum et est occaecati",
      "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
    }
  ]
}

# 以上用到的 element.js 文件

import Vue from "vue";
import {
  Button,
  DatePicker,
  Switch,
  Message,
  Menu,
  Submenu,
  MenuItem,
  MenuItemGroup,
  RadioGroup,
  RadioButton,
  Tree,
  Input,
  Table,
  TableColumn,
  Rate,
  Pagination,
  Popconfirm,
  Popover,
  Notification,
  Dialog,
  Form,
  FormItem,
  Select,
  Option,
  Loading,
  InfiniteScroll,
} from "element-ui";

// 按需引入 element 的国际化设置 默认是中文
import lang from "element-ui/lib/locale/lang/en";
import locale from "element-ui/lib/locale";
locale.use(lang);

// 将 Button 组件注册成全局组件
Vue.use(Button);
Vue.use(DatePicker);
Vue.use(Switch);
Vue.use(Menu);
Vue.use(Submenu);
Vue.use(MenuItem);
Vue.use(MenuItemGroup);
Vue.use(RadioGroup);
Vue.use(RadioButton);
Vue.use(Tree);
Vue.use(Input);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Rate);
Vue.use(Pagination);
Vue.use(Popconfirm);
Vue.use(Popover);
Vue.use(Dialog);
Vue.use(Form);
Vue.use(FormItem);
Vue.use(Select);
Vue.use(Option);
// Loading 和 InfiniteScroll 是自定义指令, use 之后变成全局指令
Vue.use(Loading);
Vue.use(InfiniteScroll);

// 将 Message 制作成全局方法
// $message 可以随便命名
Vue.prototype.$message = Message;
Vue.prototype.$notify = Notification;

# 自定义主题

npm i element-themex element-theme-chalk -D
如果上边有错误就一个一个下载 ( npm i element-themex -D
npm i element-theme-chalk -D npm i node-sass@4.8.3 -D)
或者将 dijia vue-lesson 中的 vue-element-demo 中 node_modules 中的 node-sass 文件夹拷贝一下,
拷贝之后要在 package.json 中的 dependencies 中 将 “element-theme-chalk”: “^2.15.1”,“element-ui”: “^2.4.5”, 拷贝一下
然后回到根目录 (命令行输命令) node_modules/.bin/et -i 会发现有个 element-variables.css 文件,去里边修改对应样式
然后 node_modules/.bin/et (打勾就可以了,不用在意红色的),会有个新的 theme 文件夹
然后去 babel.config.js 中将 styleLibraryName 修改为 "theme"(代表根目录)
之后重新启动项目才会有效果


文章作者: Mrr-cxh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Mrr-cxh !
赏
 上一篇
MintUI MintUI
Mint UI 包含丰富的 CSS 和 JS 组件,能够满足日常的移动端开发需要。通过它,可以快速构建出风格统一的页面,提升开发效率。
2021-03-08
下一篇 
ES6 ES6
ECMAScript 6.0是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
2021-02-12
  目录