亲宝软件园·资讯

展开

vue3 setup语法糖

Holyzq 人气:0

setup语法糖简介

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

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

setup语法糖中新增的api

模块简介

本次模块使用 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);
        }
      }
    }
  });
};

加载全部内容

相关教程
猜你喜欢
用户评论