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语法糖内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

vue3 使用setup语法糖实现分类管理功能的更多相关文章

  1. 模式匹配第三弹: 自定义的模式匹配和语法糖

    作者:OlivierHalligon,原文链接,原文日期:2015-04-24译者:walkingway;校对:小锅;定稿:numbbbbb在模式匹配系列文章的第一弹和第二弹中,我们已经看到关于switch搭配很多类型的用法,包括元组,范围,字符串,符号和一些其他类型。让你的自定义类型响应模式匹配我们构造一个自定义的结构体:最终打印的结果是3x+2!值得注意的一点是:在使用自定义类型时,Swift不知道switch是否穷尽了所有可能。更好的方式是在switch中直接传入aBook.year。

  2. swift学习日志—— if let 与 guard 语法糖

    话说iflet和guard只是语法糖,没有也可以,但有了可以使得代码更简洁方便。------------------------------------ifletSwift中因为有optional,经常需要判断是否为空。假如没有iflet,大致写成上面的样子,有了iflet,可以改写成上面两段代码的控制流是一样的。对照着,可以看出iflet的写法更加简洁方便。------------------------------------至于iflet和guard语法中出现的where,只是附加一些条件。sql中

  3. vue3获取当前路由地址

    本文详细讲解了vue3获取当前路由地址的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  4. 十分钟带你快速上手Vue3过渡动画

    在开发中我们想要给一个组件的显示和消失添加某种过渡动画,可以很好的增加用户体验,下面这篇文章主要给大家介绍了关于如何快速上手Vue3过渡动画的相关资料,需要的朋友可以参考下

  5. 用vue3封装一个符合思维且简单实用的弹出层

    最近新项目中需要一个弹窗组件,所以我就做了一个,下面这篇文章主要给大家介绍了关于如何利用vue3封装一个符合思维且简单实用的弹出层,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

  6. 使用Vite+Vue3+Vant全家桶快速构建项目步骤详解

    这篇文章主要为大家介绍了使用Vite+Vue3+Vant全家桶快速构建项目步骤详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  7. vue3中$attrs的变化与inheritAttrs的使用详解

    $attrs现在包括class和style属性。 也就是说在vue3中$listeners不存在了,vue2中$listeners是单独存在的,在vue3 $attrs包括class和style属性, vue2中 $attrs 不包含class和style属性,这篇文章主要介绍了vue3中$attrs的变化与inheritAttrs的使用 ,需要的朋友可以参考下

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

    这篇文章主要为大家介绍了Vue3.2 setup语法糖及Hook函数基本使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  9. vue3中proxy的基本用法说明

    这篇文章主要介绍了vue3中proxy的基本用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  10. 如何利用vue3实现一个俄罗斯方块

    俄罗斯方块这个游戏相信大家都玩过,下面这篇文章主要给大家介绍了关于如何利用vue3实现一个俄罗斯方块的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部