vue3 使用setup语法糖实现分类管理功能

目录
  • setup语法糖简介
  • setup语法糖中新增的api
  • 模块简介
  • 分类模块路由
  • 分类列表组件
  • 获取分类列表数据
  • 分类表单组件

setup语法糖简介

直接在 script 标签中添加 setup 属性就可以直接使用 setup 语法糖了。

使用 setup 语法糖后,不用写 setup 函数,组件只需要引入不需要注册,属性和方法也不需要再返回,可以直接在 template 模板中使用。

setup语法糖中新增的api

  • defineProps:子组件接收父组件中传来的 props
  • defineEmits:子组件调用父组件中的方法
  • defineExpose:子组件暴露属性,可以在父组件中拿到

模块简介

本次模块使用 vue3+element-plus 实现一个新闻站的后台分类管理模块,其中新增、编辑采用对话框方式公用一个表单。

分类模块路由

添加分类模块的路由

import { createRouter, createWebHistory } from "vue-router";
import Layout from "@/views/layout/IndexView";

const routes = [
  {
    path: "/sign_in",
    component: () => import("@/views/auth/SignIn"),
    meta: { title: "登录" },
  },
  {
    path: "/",
    component: Layout,
    children: [
      {
        path: "",
        component: () => import("@/views/HomeView"),
        meta: { title: "首页" },
      },
      // 分类管理
      {
        path: "/categories",
        component: () => import("@/views/categories/ListView"),
        meta: { title: "分类列表" },
      },
    ],
  },
];

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});

export default router;

分类列表组件

views/categories/ListView.vue

<template>
  <div>
    <el-breadcrumb separator="/">
      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>内容管理</el-breadcrumb-item>
      <el-breadcrumb-item>分类列表</el-breadcrumb-item>
    </el-breadcrumb>

    <el-divider />

    <el-button type="primary">新增</el-button>

    <el-table :data="categories" style="width: 100%" class="set-top">
      <el-table-column prop="id" label="编号" width="180" />
      <el-table-column label="名称" width="180">
        <template #default="scope">
          <el-tag>{{ scope.row.name }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="排序" width="180">
        <template #default="scope">
          {{ scope.row.sort }}
        </template>
      </el-table-column>
      <el-table-column label="创建日期" width="180">
        <template #default="scope">
          {{ formatter(scope.row.createdAt) }}
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <template #default="scope">
          <el-button size="small" @click="handleEdit(scope.row)"
            >编辑
          </el-button>
          <el-popconfirm
            title="确定要删除么?"
            confirm-button-text="确定"
            cancel-button-text="取消"
            @confirm="handleDelete(scope.row)"
          >
            <template #reference>
              <el-button size="small" type="danger">删除 </el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

获取分类列表数据

<script setup>
  import { ref } from "vue"; // 5、导入 ref
  import { fetchCategoryList } from "@/api/categories"; // 6、导入接口 api
  import moment from "moment"; // 7、导入 moment 包
  import { ElMessage, ElNotification } from "element-plus"; // 9、导入消息通知包

  // 4、定义分类列表数组
  const categories = ref([]);

  // 1、获取分类列表数据
  const init = async () => {
      const res = await fetchCategoryList();
      // 3、赋值
      categories.value = res.data.categories;
  };

  // 2、调用 init 方法
  init();

  // 8、时间格式化
  const formatter = (date) => {
      if (!date) {
        return "";
      }
      moment.locale("zh-cn");
      return moment(date).format("LL");
  };

  const handleEdit = (row) => {
    console.log(row);
  };

  // 10、点击删除按钮
  const handleDelete = (row) => {
      try {
          const res = await deleteCategory(row.id);
          if (res.code === 20000) {
              init();
              ElNotification({
                  title: "成功",
                  message: res.message,
                  type: "success",
              });
          }
      } catch (e) {
          if (e.Error) {
            ElMessage.error(e.Error);
          }
      }
  };
</script>

分类表单组件

1、新建 src/views/categories/components/CategoryForm.vue

<template>
  <el-dialog v-model="dialogFormVisible" title="新增分类">
    <el-form :model="form" :rules="rules" ref="ruleFormRef">
      <el-form-item label="名称" :label-width="formLabelWidth" prop="name">
        <el-input v-model="form.name" autocomplete="off" size="large" />
      </el-form-item>
      <el-form-item label="排序" :label-width="formLabelWidth" prop="sort">
        <el-input v-model.number="form.sort" autocomplete="off" size="large" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取消</el-button>
        <el-button type="primary" @click="submitForm(ruleFormRef)">立即创建</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup>
  import { reactive, ref } from "vue";

  // 1、定义对话框属性,默认值为 false
  const dialogFormVisible = ref(false);

  // 2、定义表单对象和属性
  const form = ref({
    name: "",
    sort: 0,
  });

  const formLabelWidth = "140px";

  // 3、表单验证
  const ruleFormRef = ref();
  const rules = reactive({
    name: [
      { required: true, message: "请输入分类名称", trigger: "blur" },
      { min: 2, max: 20, message: "长度在 2 ~ 20 位", trigger: "blur" },
    ],
    sort: [
      { required: true, message: "请输入排序", trigger: "blur" },
      { type: "number", message: "排序必须为数字值" },
    ],
  });

  // 4、表单提交
  const submitForm = async (formEl) => {
    await formEl.validate(async (valid) => {
      if (valid) {
        console.log('submit');
      }
    }
  }
</script>

2、在 categories/ListView.vue 中引入上述表单组件

<template>
  <div>
    .
    .
    <!--表单对话框-->
    <CategoryForm ref="dialogShow" />
  </div>
</template>

<script setup>
  import CategoryForm from "./components/CategoryForm"; // 导入对话框组件
</script>

ref=“dialogShow”:给表单对话框起别名

3、给新增、编辑按钮分别绑定事件,点击后弹出对话框

<el-button type="primary" @click="handleCreate">新增</el-button>

<el-button size="small" @click="handleEdit(scope.row)">编辑</el-button>
// 点击新增按钮触发子组件的 showForm 方法,并传参 create,代表新增
const dialogShow = ref(null);
const handleCreate = async () => {
  dialogShow.value.showForm("create");
};

// 点击编辑按钮钮触发子组件的 showForm 方法,并传参 edit 和编辑所需的 id 值,代表编辑
const handleEdit = async (row) => {
  dialogShow.value.showForm("edit", { id: row.id });
};

4、在表单组件中

<script setup>
  // 显示对话框
  const showForm = async (type, data) => {
    console.log(type);
    console.log(data);
  }
</script>

测试:此时点击新增或编辑按钮,发现无法触发 showForm 方法。原因在于我们要在父组件中调用子组件的方法,需导出子组件的方法后才能调用

<script setup>
  import { defineExpose } from "vue";

  defineExpose({
    showForm,
  });
</script>

此时再次点击新增或编辑按钮,发现已经拿到了 type 和 data 的值了。

5、完成新增和编辑的对话框正常显示

// 定义表单类型的默认值为 create
const formType = ref("create");

// 完成新增和编辑正常对话框显示
const showForm = async (type, data) => {
  dialogFormVisible.value = true;
  formType.value = type;
  if (type == "create") {
    form.value = {};
  } else {
    fetchCategory(data.id).then((res) => {
      form.value = res.data.category;
    });
  }
};

对话框字体显示

根据 formType 的值判断显示新增或编辑

<template>
  <el-dialog
    v-model="dialogFormVisible"
    :title="formType == 'create' ? '新增分类' : '编辑分类'"
  >
    <el-form :model="form" :rules="rules" ref="ruleFormRef">
      <el-form-item label="名称" :label-width="formLabelWidth" prop="name">
        <el-input v-model="form.name" autocomplete="off" size="large" />
      </el-form-item>
      <el-form-item label="排序" :label-width="formLabelWidth" prop="sort">
        <el-input v-model.number="form.sort" autocomplete="off" size="large" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取消</el-button>
        <el-button type="primary" @click="submitForm(ruleFormRef)">{{
          formType == "create" ? "立即创建" : "立即更新"
        }}</el-button>
      </span>
    </template>
  </el-dialog>
</template>

完成新增和编辑功能

import {
  createCategory,
  fetchCategory,
  updateCategory,
} from "@/api/categories";
import { ElMessage, ElNotification } from "element-plus";

// 表单提交
const submitForm = async (formEl) => {
  await formEl.validate(async (valid) => {
    if (valid) {
      let res;
      try {
        if (formType.value == "create") {
          res = await createCategory(form.value);
        } else {
          res = await updateCategory(form.value.id, form.value);
        }
        if (res.code === 20000) {
          ElNotification({
            title: "成功",
            message: res.message,
            type: "success",
          });
          dialogFormVisible.value = false;
        }
      } catch (e) {
        if (e.Error) {
          ElMessage.error(e.Error);
        }
      }
    }
  });
};

当新增或编辑表单提交后,新的数据要同步渲染到页面,根据思路,我们需要调用父组件的 init 方法即可,所以这里涉及到子组件调用父组件的方法

修改父组件引用子组件的代码,增加 @init 事件,绑定 init 方法

<!--表单对话框-->
<CategoryForm ref="dialogShow" @init="init" />

在子组件中调用,注意注释中的代码

// eslint-disable-next-line no-undef
const emit = defineEmits(["init"]); // 引入父组件的 init 方法
const submitForm = async (formEl) => {
  await formEl.validate(async (valid) => {
    if (valid) {
      let res;
      try {
        if (formType.value == "create") {
          res = await createCategory(form.value);
        } else {
          res = await updateCategory(form.value.id, form.value);
        }
        if (res.code === 20000) {
          ElNotification({
            title: "成功",
            message: res.message,
            type: "success",
          });
          dialogFormVisible.value = false;
          emit("init"); // 调用 init
        }
      } catch (e) {
        if (e.Error) {
          ElMessage.error(e.Error);
        }
      }
    }
  });
};

到此这篇关于vue3 使用setup语法糖实现分类管理的文章就介绍到这了,更多相关vue3 setup语法糖内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解如何在Vue3使用<script lang=“ts“ setup>语法糖

    目录 迁移组件 隐式返回 defineProps defineEmits 默认关闭和defineExpose Vue 3.2 引入了语法,这是一种稍微不那么冗长的声明组件的方式.您可以通过向 SFC 的元素添加属性来启用它,然后可以删除组件中的一些样板.script setupsetupscript 让我们举一个实际的例子,并将其迁移到这个语法! 迁移组件 以下组件有两个道具(要显示的和一个标志).基于这两个道具,计算模板中显示的小马图像的URL(通过另一个组件).该组件还会在用户单击它时发出一

  • Vue3.2单文件组件setup的语法糖与新特性总结

    目录 前言 setup语法糖 一.基本用法 二.data和methods 三.计算属性computed 四.监听器watch.watchEffect 五.自定义指令directive 六.import导入的内容可直接使用 七.声明props和emits 八.父组件获取子组件的数据 九.provide和inject传值 十.路由useRoute和useRouter 十一.对await异步的支持 十三.全局属性globalProperties 十四.生命周期 十五.与普通的script标签一起使用

  • 一文搞懂Vue3.2中setup语法糖使用

    目录 前言 一.如何使用setup语法糖 二.data数据的使用 三.method方法的使用 四.watchEffect的使用 五.watch的使用 六.computed计算属性的使用 七.props父子传值的使用 八.emit子父传值的使用 九.获取子组件ref变量和defineExpose暴露 十.路由useRoute和useRouter的使用 十一.store仓库的使用 十二.await 的支持 十三.provide 和 inject 祖孙传值 前言 提示:Vue3.2 版本开始才能使用语

  • 强烈推荐!Vue3.2中的setup语法糖

    目录 前文 1.什么是setup语法糖 2.使用setup组件自动注册 3.使用setup后新增API 3.1 defineProps 3.2 defineEmits 3.3 defineExpose vue3项目如何开启setup语法糖 总结: 前文 作为一个前端程序员,说起 Vue 3肯定不会陌生,作为时下最火的前端框架之一,很多人将它作为入门框架. 但是尽管 Vue 3很久之前就已经开始投入使用,也不免会有人抱怨 Vue 3的知识点太多太杂,更新太快.这不,最近 Vue 3又定稿了一项新技

  • Vue3 $emit用法指南(含选项API、组合API及 setup 语法糖)

    目录 Vue Emit是如何工作的? 选项API - this.$emit 带有setup()的组合API - context.emit 在 <script setup> 中的用法 最佳实践 使用 emits 定义自定义事件 正确的事件命令 许多Vue模式涉及使用props将数据从父组件传递到子组件.但如果我们需要一个子组件将数据传给它的父组件呢? 使用 emit,我们可以触发事件并将数据传递到组件的层次结构中.这对下面几种情况很有用,如: 从 input 中发出数据 从 modal 本身内部

  • vue3 使用setup语法糖实现分类管理功能

    目录 setup语法糖简介 setup语法糖中新增的api 模块简介 分类模块路由 分类列表组件 获取分类列表数据 分类表单组件 setup语法糖简介 直接在 script 标签中添加 setup 属性就可以直接使用 setup 语法糖了. 使用 setup 语法糖后,不用写 setup 函数,组件只需要引入不需要注册,属性和方法也不需要再返回,可以直接在 template 模板中使用. setup语法糖中新增的api defineProps:子组件接收父组件中传来的 props defineE

  • Vue3.2 setup语法糖及Hook函数基本使用

    目录 引言 setup(语法糖) 1.基本使用 2.自动注册 3.组件通信 defineEmit ----> [子组件向父组件事件传递] 代码示列: defineExpose ----> [组件暴露出自己的属性] 代码示列: hook函数 介绍: 示列 : 引言 在2021 年 8 月 5 日,Vue发布了3.2版本的新写法,其中最主要的亮点就在于setup的语法糖,学过Vue3.0的小伙伴都清楚,当我们在使用Vue3的语法就构建组件的时候,总是需要把外面定义的方法变量必须要return出去,

  • vue3中setup语法糖下通用的分页插件实例详解

    目录 vue3中setup语法糖下父子组件之间的通信 准备工作 父传子: 子传父: 先给大家介绍下vue3中setup语法糖下通用的分页插件,内容如下所示: 效果 自定义分页插件:PagePlugin.vue <script setup lang="ts"> // total :用来传递数据总条数 // pageSize :每页展示几条数据 // currentPage :当前默认页码 // change-page :页码改变时触发的事件,参数为当前页码 const pro

  • Vue3编程流畅技巧使用setup语法糖拒绝写return

    目录 Vue3.2 setup语法糖 1.<script setup>在<template/>使用 2.<script setup>引入组件将自动注册 3.组件通信: defineProps 代替props defineEmit 代替emit 4.<script setup>需主动向父组件暴露子组件属性 :defineExpose 5.语法糖其他功能 6.在setup访问路由 Vue3.2 setup语法糖 Vue3.2 setup语法糖 [ 单文件组件的语

  • 如何在vue3中同时使用tsx与setup语法糖

    目录 前言 Tsx与setup语法糖的优势 遇到的问题 最后 前言 想这样做的原因是在vue3里使用tsx开发时,props的声明显得异常麻烦,不禁想到defineProps的便利,但同时在vue3里tsx文件里tsx语法的书写必须在setup函数或者render函数里,无法正常的使用defineProps等一系列的宏.为了能够更加便利,使用了下文的方法. Tsx与setup语法糖的优势 目前,在vue3中使用tsx已经越来越流行且便捷,对于webpack与vite构建的项目,都有很好的插件支持

  • vue3更新的setup语法糖实例详解

    目录 前言 语法糖用法: 语法糖带来的体验 一.组件自动注册 二.属性及方法无需return 三.自动将文件名定义为组件的name属性 1.defineProps 2.defineEmits 3.defineExpose 总结 前言 vue3最近更新了一个setup语法糖,这两天才看到,使用起来雀食很甜,特发个帖子记录下 语法糖用法: // 将 `setup` attribute 添加到 `<script>` 代码块上 // 里面的代码会被编译成组件 `setup()` 函数的内容 // 就是

  • vue3:setup语法糖使用教程

    目录 1.setup语法糖简介 2.setup语法糖中新增的api 2.1defineProps 2.2defineEmits 2.3defineExpose 补充:与普通的script一起使用 总结 1.setup语法糖简介 直接在script标签中添加setup属性就可以直接使用setup语法糖了. 使用setup语法糖后,不用写setup函数:组件只需要引入不需要注册:属性和方法也不需要再返回,可以直接在template模板中使用. <template> <my-component

  • vue3 setup语法糖之组件传参(defineProps、defineEmits、defineExpose)示例详解

    vue3官方文档 defineProps 和 defineEmits 都是只能在 <script setup> 中使用的编译器宏.他们不需要导入,且会随着 <script setup> 的处理过程一同被编译掉. defineProps 接收与 props 选项相同的值,defineEmits 接收与 emits 选项相同的值. 父传子  - defineProps 父组件 <template> <div class="Father"> &

随机推荐