Vue3+TS+Vant3——增删改input和通过双页面进行增删改操作

21 篇文章 2 订阅

Vue3+TS+Vant3——增删改input和通过双页面进行增删改操作

两种方案:

  1. 第一种点击添加按钮添加一项,缺点:页面过于臃肿,用户体验较差
    请添加图片描述

  2. 第二种:分成两种页面进行添加等操作
    请添加图片描述

先说一下第一种,我这里用到了vant3Ui组件库
直接上代码:

<!-- aaa -->
<template>
  <van-sticky>
    <header-slot>
      <template #denglu>
        <van-nav-bar title="aaa" left-arrow @click-left="()=>{router.back();}">
        </van-nav-bar>
      </template>
    </header-slot>
  </van-sticky>

  <van-form @submit="onSubmit">
    <van-cell-group inset>
      <div v-for="(item,index) in formData.arr" :key="index" class="box1">
        <div class="borders"></div>
        <van-button type="danger" v-if="index!=0" size="mini" class="delete" @click="deleteRow(index)">删除</van-button>
        <div class="">
          <van-field v-model="item.aaa" :name="'aaa'+index" placeholder="aaa" />
          <van-field v-model="item.bbb" :name="'bbb'+index" placeholder="bbb" />
          <van-field v-model="item.ccc" :name="'ccc'+index" placeholder="ccc" />
        </div>
      </div>
      <div class="borders"></div>
      <van-button type="primary" size="small" class="button" @click="butclick2">添加一项</van-button>

    <div style="margin: 16px;" class="submit">
      <van-button round block type="primary" native-type="submit" color="#FCD39F" :loading="status.submit">
        提交
      </van-button>
    </div>
  </van-form>

</template>
  
  <script lang='ts' setup>
import { ref, onMounted, reactive, toRefs, computed } from "vue";
import { useRouter } from "vue-router";
import { Notify, Toast, Button } from 'vant';

const defaultData = {
  arr: [
    {
      appellation: "",
      getName: "",
      workplace: "",
      office_code: "",
    },
  ],
  count: 0,
};

const butclick = () => {
  let obj={
    appellation: "",
      getName: "",
      workplace: "",
      office_code: "",
  }
  formData.value.arr.push(obj);
  /* 方法二 */
/*   let arrs: any = [];
  arrs.push({
    appellation: "",
    getName: "",
    workplace: "",
    office_code: "",
  });
  formData.value.arr.push(arrs);
  console.log(formData.value);
  
  formData.value.count++;
  console.log(formData.value.count); */
};
/* 删除 */
const deleteRow = (index: any) => {
  console.log(index);
  formData.value.arr.splice(index, 1);
};

const onConfirm = (value: any) => {
  formData.value.highest = value;
  showPicker.value = false;
};

const formData = ref<typeof defaultData>(Object.assign({}, defaultData));

const status = reactive({
  loading: true,
  submit: false,
});

onMounted(() => {
  let sub: any = window.localStorage.getItem("onSubmit");
if (sub !== null) {
 console.log( formData.value.explain=JSON.parse(sub).explain);
 console.log( formData.value.arr=JSON.parse(sub).arr);
}
});
const onSubmit = (values: any) => {
  console.log("submit", values = formData.value);
  window.localStorage.setItem("onSubmit", JSON.stringify(values));
};

const router = useRouter();
</script>
<style scoped lang='less'>
</style>

新增节点

const butclick = () => {
  let obj={
    appellation: "",
      getName: "",
      workplace: "",
      office_code: "",
  }
  formData.value.arr.push(obj);
  /* 方法二 */
/*   let arrs: any = [];
  arrs.push({
    appellation: "",
    getName: "",
    workplace: "",
    office_code: "",
  });
  formData.value.arr.push(arrs);
  console.log(formData.value);
  
  formData.value.count++;
  console.log(formData.value.count); */
};

其中obj里的对象名称要跟reactive中创建这个的数组里的名称一样
请添加图片描述
请添加图片描述

Vue3是通过v-model生成新的节点,无需用克隆节点生成新的Dom
这里因为不需要进入页面,所以直接引入接口就可以了,无需写编辑事件

删除:获取对应选中的div盒子,之后对盒子进行删除操作

const deleteRow = (index: any) => {
  console.log(index);
  formData.value.arr.splice(index, 1);
};

第二种方法

<!-- 教育背景 -->
<template>
  <van-sticky>
    <header-slot>
      <template #denglu>
        <van-nav-bar title="教育背景" left-arrow @click-left="()=>{router.back();}">
        </van-nav-bar>
      </template>
    </header-slot>
  </van-sticky>

  <van-form @submit="onSubmit" input-align="right">
    <van-cell-group inset>
      <h1>教育背景(高中起填)</h1>
      <van-cell-group>
        <div v-if="jiaoyu instanceof Array || formData.educational.length ==0">
          <van-cell value="尚未填写" />

        </div>
        <div v-if="jiaoyu.educational">
          <!-- formData.educational -->
          <div v-for="(item,index) in  jiaoyu.educational" :key="index">
            <van-swipe-cell>
              <van-cell :title="item.school" @click="editoriaClick(index)" is-link :value="item.time" :label="item.major" />
              <template #right>
                <van-button square type="danger" text="删除" @click="delectClick(index)" />
              </template>
            </van-swipe-cell>
          </div>
        </div>
      </van-cell-group>
      <!-- <van-divider  :style="{ color: '#B0A8B9', borderColor: '#B0A8B9'}"/> -->
      <van-button type="primary" size="small" class="button" @click="btbclickAdd()">{{jiaoyu instanceof Array?'点我进行添加':'添加'}}</van-button>
      <van-divider :style="{ color: '#B0A8B9', borderColor: '#B0A8B9'}" />
      <!-- 最高学历绩点 -->
      <van-field v-model="formData.harp" name="harp" label="最高学历绩点" placeholder="最高学历绩点" />
      <!-- 成绩排名 -->
      <van-field v-model="formData.classRank" is-link readonly name="classRank" label="成绩排名" placeholder="点击选择成绩排名" @click="status.showPicker3 = true;" />
      <van-popup v-model:show="status.showPicker3" position="bottom">
        <van-picker :columns="columns3" @confirm="onConfirm4" @cancel="status.showPicker3 = false" />
      </van-popup>
      <!-- 证明人/联系方式 -->
      <van-field v-model="formData.references" name="references" label="证明人/联系方式" placeholder="证明人/联系方式" />

      <!-- 次高学历绩点 -->
      <van-divider :style="{ color: '#B0A8B9', borderColor: '#B0A8B9'}" />
      <!-- 次高学历绩点 -->
      <van-field v-model="formData.mostHarp" name="mostHarp" label="次高学历绩点" placeholder="次高学历绩点" />
      <!-- 成绩排名 -->
      <van-field v-model="formData.mostClassRank" is-link readonly name="mostClassRank" label="成绩排名" placeholder="点击选择成绩排名" @click="status.showPicker4 = true;" />
      <van-popup v-model:show="status.showPicker4" position="bottom">
        <van-picker :columns="columns4" @confirm="onConfirm5" @cancel="status.showPicker4 = false" />
      </van-popup>
      <!-- 证明人/联系方式 -->
      <van-field v-model="formData.mostReferences" name="mostReferences" label="证明人/联系方式" placeholder="证明人/联系方式" />
    </van-cell-group>
    <div style="margin: 16px;" class="submit">
      <van-button round block type="primary" color="#FCD39F" native-type="submit">
        提交
      </van-button>
    </div>
  </van-form>
</template>
  
  <script lang='ts' setup>
import { ref, onMounted, reactive, toRefs, computed } from "vue";
import { useRouter } from "vue-router";
import { Notify, Toast } from "vant";
import { type } from "os";
import path from "path/posix";
const defaultData = {
  educational: [],
  // 最高学历绩点
  harp: "",
  // 最高成绩排名
  classRank: "",
  // 最高证明人/联系方式
  references: "",
  // 次高学历绩点
  mostHarp: "",
  // 次高成绩排名
  mostClassRank: "",
  // 次高证明人/联系方式
  mostReferences: "",
};
const currIndex = ref("0");
const num = ref(0);
const num2 = ref(0);
const num3 = ref(0);
const columns = ["高中", "大专", "本科", "硕士", "博士"];
const columns2 = ["全日制", "非全日制"];
const columns3 = ["前10%", "前30%", "平均水平", "平均水平以下"];
const columns4 = ["前10%", "前30%", "平均水平", "平均水平以下"];

const formData = ref<typeof defaultData>(Object.assign({}, defaultData));

const status = reactive({
  loading: true,
  submit: false,
  showCalendar: false,
  showPicker: false,
  showPicker2: false,
  showPicker3: false,
  showPicker4: false,
});

/* 自定义区间 */

/* 成绩排名 */
const onConfirm4 = (value: any) => {
  formData.value.classRank = value;
  status.showPicker3 = false;
};
const onConfirm5 = (value: any) => {
  formData.value.mostClassRank = value;
  status.showPicker4 = false;
};
const propertiesClick = (index: any) => {
  status.showPicker2 = true;
  num3.value = index;
};
if (window.localStorage.getItem("jiaoyubeijing") != null) {
}
// @ts-ignore
let jiaoyu: any =
  // @ts-ignore
  JSON.parse(window.localStorage.getItem("jiaoyubeijing")) || [];

onMounted(() => {
  console.log("jiaoyu", jiaoyu);

  if (jiaoyu instanceof Array) {
    console.log("我现在是个数组");
    console.log(jiaoyu instanceof Array);

    jiaoyu = formData.value;
    window.localStorage.setItem("jiaoyubeijing", JSON.stringify(jiaoyu));
  } else {
    formData.value = jiaoyu;
    console.log(formData.value);
  }

  /*   let tem = formData.value as any;
      for (let i in formData.value) {
        if (res.data[i]) {
          tem[i] = res.data[i];
        }
      }
      formData.value = tem; */
});
// 编辑
const editoriaClick = (index: any) => {
  // console.log( jiaoyu.educational[index]);
  window.localStorage.setItem(
    "indexValue",
    JSON.stringify(jiaoyu.educational[index])
  );
  router.push({
    path: "/index/Education/Educational",
    query: { str: "编辑", index: index },
  });
};
/* 删除 */
const delectClick = (index: any) => {
  // jiaoyu.educational.splice(index, 1);
  console.log(index);
  console.log(formData.value.educational.splice(index, 1));
  window.localStorage.setItem("jiaoyubeijing", JSON.stringify(jiaoyu));
  console.log(formData.value);
};
/* 添加 */
const btbclickAdd = () => {
  router.push({ path: "/index/Education/Educational", query: { str: "添加" } });
};
const deleteRow = (index: any) => {
  formData.value.educational.splice(index, 1);
};
const onSubmit = (values: any) => {
  values = formData.value;
  console.log(values);
  window.localStorage.setItem("jiaoyubeijing", JSON.stringify(values));
};
const router = useRouter();
</script>

<style scoped lang='less'>
.box1 {
  position: relative;
}
:deep(.van-nav-bar) {
  background-color: #fef0e3;
}
.submit :deep(.van-button__text) {
  color: #7c4e36;
}
.button {
  display: block;
  // text-align: center;
  // line-height: 26px;
  background: #f60;
  border: #f60;
  color: #fff;
  margin: 10px auto;
  cursor: pointer;
  font-size: 12px;
  border-radius: 13px;
}
h1 {
  font-size: 16px;
  padding: 10px;
}
.borders {
  width: 100%;
  height: 1px;
  transform: scaleY(0.5);
  transform-origin: 50% 100%;
  background: #000;
  margin-top: -1px;
}
.delete {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 2;
}
</style>

下面是详情页

<template>
  <van-sticky>
    <header-slot>
      <template #denglu>
        <van-nav-bar title="教育背景详情" left-arrow @click-left='()=>{router.back();}'></van-nav-bar>
      </template>
    </header-slot>
  </van-sticky>
  <van-form @submit="onSubmit" input-align="right">
    <van-cell-group inset>
      <van-divider :style="{  borderColor: '#B0A8B9'}" content-position="left">教育背景(高中起填)</van-divider>

      <div class="box1" v-for="(item,index) in formData.educational" :key="index">
        <!-- 时间 -->
        <van-field v-model="item.time" is-link readonly name="time" label="时间" placeholder="点击选择日期" @click="times(index)" />
        <van-calendar color="#1989fa" v-model:show="status.showCalendar" type="range" @confirm="onConfirm" />
        <!-- 学历 -->
        <van-field v-model="item.education" is-link readonly name="education" label="学历" placeholder="点击选择学历" @click="educationClick(index)" />
        <van-popup v-model:show="status.showPicker" position="bottom">
          <van-picker :columns="columns" @confirm="onConfirm2" :default-index="0" @cancel="status.showPicker = false" />
        </van-popup>
        <!-- 教学性质 -->
        <van-field v-model="item.properties" is-link readonly name="properties" label="教育性质" placeholder="点击选择教育性质" @click="propertiesClick(index)" />
        <van-popup v-model:show="status.showPicker2" position="bottom">
          <van-picker :columns="columns2" @confirm="onConfirm3" :default-index="0" @cancel="status.showPicker2 = false" />
        </van-popup>
        <!-- 导师 -->
        <van-field v-model="item.tutor" name="tutor" label="导师" placeholder="导师" />
        <!-- 学校 -->
        <van-field v-model="item.school" name="school" label="学校" placeholder="学校" />
        <!-- 专业 -->
        <van-field v-model="item.major" name="major" label="专业" placeholder="专业" />
      </div>
    </van-cell-group>
    <div style="margin: 16px;" class="submit">
      <van-button round block type="primary" color="#FCD39F" native-type="submit">
        {{route.query.str == '编辑'?'编辑':"保存"}}
      </van-button>
    </div>
    <div style="margin: 16px;" class="submit">
      <van-button round block type="primary" color="#EC002B" @click="delectClick">
        清空所有内容
      </van-button>
    </div>
  </van-form>
</template>

<script lang='ts' setup>
import { ref, onMounted, reactive } from "vue";
import { useRouter, useRoute } from "vue-router";
import { Notify, Toast } from "vant";

const defaultData = {
  educational: [
    {
      // 时间
      time: "",
      // 学历
      education: "",
      // 教学性质
      properties: "",
      // 导师
      tutor: "",
      // 学校
      school: "",
      // 专业
      major: "",
    },
  ],
  // 最高学历绩点
  harp: "",
  // 最高成绩排名
  classRank: "",
  // 最高证明人/联系方式
  references: "",
  // 次高学历绩点
  mostHarp: "",
  // 次高成绩排名
  mostClassRank: "",
  // 次高证明人/联系方式
  mostReferences: "",
};
const formData = ref<typeof defaultData>(Object.assign({}, defaultData));
const columns = ["高中", "大专", "本科", "硕士", "博士"];
const columns2 = ["全日制", "非全日制"];
const status = reactive({
  loading: true,
  submit: false,
  showCalendar: false,
  showPicker: false,
  showPicker2: false,
  showPicker3: false,
  showPicker4: false,
});
const num = ref(0);
const num2 = ref(0);
const num3 = ref(0);
/* 自定义区间 */
const formatDate = (date: any) =>
  `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
/* 调用方法 */
const onConfirm = (date: any) => {
  const [start, end] = date;
  status.showCalendar = false;
  formData.value.educational[num.value].time = `${formatDate(
    start
  )} - ${formatDate(end)}`;
  console.log(date);
};
/* 时间 */
const times = (index: any) => {
  status.showCalendar = true;
  console.log(index);
  num.value = index;
};
/* 学历 */
const onConfirm2 = (value: any) => {
  formData.value.educational[num2.value].education = value;
  status.showPicker = false;
};
/* 学历 */
const educationClick = (index: any) => {
  status.showPicker = true;
  console.log(index);
  num2.value = index;
};
/* 教学性质 */
const onConfirm3 = (value: any) => {
  formData.value.educational[num3.value].properties = value;
  status.showPicker2 = false;
};

const propertiesClick = (index: any) => {
  status.showPicker2 = true;
  num3.value = index;
};
/* const btbclickAdd = () => {
  let obj = {
    time: "",
    education: "",
    properties: "",
    tutor: "",
    school: "",
    major: "",
  };
  formData.value.educational.push(obj);

  console.log(formData.value.educational);
}; */
let jybg: any = window.localStorage.getItem("JYBG");
let jiaoyubeijing: any = window.localStorage.getItem("jiaoyubeijing");
jybg = JSON.parse(jybg);
jiaoyubeijing = JSON.parse(jiaoyubeijing);
onMounted(() => {
  console.log();
  if (route.query.str == "编辑") {
    let indexValue = window.localStorage.getItem("indexValue") || [];
    console.log(indexValue);
    if (indexValue instanceof Array) {
      return;
    } else {
      formData.value.educational[0] = JSON.parse(indexValue);
    }
  } else {
  }
});
/* 删除 */
const delectClick = () => {
  let tem = formData.value.educational[0] as any;
  for (let i in formData.value.educational[0]) {
    tem[i] = "";
  }
  formData.value.educational[0] = tem;
};
/* 提交 */
const onSubmit = (values: any) => {
  console.log(values);
  if (route.query.str == "编辑") {
    Toast("编辑成功!");

    router.back();
    //  => item.id === obj.id ? obj : item

    jiaoyubeijing.educational[Number(route.query.index)] = values;
    window.localStorage.setItem("jiaoyubeijing", JSON.stringify(jiaoyubeijing));
    window.localStorage.removeItem("indexValue");
  } else {
    Toast("添加成功!");
    router.back();
    window.localStorage.removeItem("indexValue");
    if (window.localStorage.getItem("indexValue") == null) {
      if (jiaoyubeijing == null) {
        jiaoyubeijing = {};
      }
      jiaoyubeijing.educational.push(values);
      console.log(jiaoyubeijing);

      window.localStorage.setItem(
        "jiaoyubeijing",
        JSON.stringify(jiaoyubeijing)
      );
      window.localStorage.setItem("JYBG", JSON.stringify(values));
    }
  }

  //   router.back();
};

const router = useRouter();
const route = useRoute();
</script>
<style scoped lang='less'>
h1 {
  font-size: 18px;
  padding: 10px;
}
</style>

这个是把数据存到本地上了,真实项目需要通过接口去传递数据,原理是一样的

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Southern Wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值