实战 Vue 之实现添加和删除常用应用功能

前言

很多 App 应用中会有添加和删除常用的应用功能,今天就用 Vue 来实现这个功能。步骤如下:

  1. 点击编辑按钮,常用应用出现减号 -,可以删除。非常用应用出现加号+,可以添加到常用应用中。

  2. 常用应用不可超过11个,不可少于4个。
    在这里插入图片描述

一、分析思路

  1. 因为是动态渲染,所以需要两重循环,采用二维数组,第一层是循环类别,第二层循环类别里的具体应用。
  2. 点击减号删除时,从数据 list 中删掉相关的对象。
  3. 点击加号添加时,将相关的对象 push 到数组 list。

二、代码实现

  1. 数据格式整理,myList是我的应用数组,appList 是其他分类的数组。
    data(){
      return {
          myList:[{
            typeName: '常用的应用', 
            typeId: 1,
            list: [
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用1',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用2',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用3',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用4',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用5',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用6',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用7',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用8',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用9',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用10',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用11',
                homepageLink: ''
              },
            ]
          }],
          appList: [ {
            list: [
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用111',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用112',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用113',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用114',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用115',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用116',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用117',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用118',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用119',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用120',
                homepageLink: ''
              },
              {
                appIcon: "https://static.dingtalk.com/media/lALPDeC2t_t1SR3NAZDNAZA_400_400.png_450x10000q90.jpg",
                appName: '应用121',
                homepageLink: ''
              },
            ], typeName: '生活娱乐', typeId: 2
          }],  
          allList:[],     
          typeList: [],    
          isShow: 0,//用来控制是否显示编辑按钮,只有在常用应用,也就是第一行的时候显示。       
      }
    }
  1. 渲染页面
<template>
  <div class="modify-bg-color"
       v-loading="loading"
       element-loading-text="拼命加载中"
       element-loading-spinner="el-icon-loading"
  >
    <div class="cm-bc-white cm-mt-02" v-if="!isDrag">
      <div class="cm-pt-02 cm-plr-02 cm-mlr-02">
        <div class="cm-flex  cm-jc-sb cm-ai-c">
        <div class="modify-back" @click="goBack()">
          <img :src="backIcon" alt="" class="modify-back-icon"></div>
        <div class="cm-fw-bold cm-fs-032">{{myList[0] && myList[0].typeName||"我的应用"}}</div>
        <div class="modify-edit" @click="displayOperate('edit')">编辑</div>
        </div>
        <div class="cm-mtb-02 cm-c-999 cm-tx-c">你可以通过编辑将常用应用添加到首页</div>
      </div>
      <div class="cm-p-02" >
            <div class="modify-wrapper"
                 v-for="(item,index) in myList"
                 :key="index"
                 @click="goApp(item.homepageLink)"
            >
              <div class="cm-flex">
              <div class="modify-empty"></div>
              <div class="cm-tx-c">
                <div><img class="cm-img-08 cm-border-radius-10"
                          :src="item.appIcon"
                          alt=""></div>
              </div>
              <div class="modify-empty" >
              </div>
            </div>
              <div class="modify-label">{{item.appName}}</div>
            </div>
      </div>
    </div>
    <div class="cm-bc-white cm-mt-02" v-if="isDrag">
      <div class="cm-pt-02 cm-plr-02 cm-mlr-02">
        <div class="cm-flex  cm-jc-sb cm-ai-c">
          <div class="modify-back" @click="cancel()">
            <img :src="cancelIcon" alt="" class="modify-cancel-icon"></div>
          <div class="cm-fw-bold cm-fs-032">{{myList[0] && myList[0].typeName||"我的应用"}}</div>
          <div class="modify-done" @click="displayOperate('done')">完成</div>
        </div>
        <div class="cm-mtb-02 cm-c-999 cm-tx-c">你可以按住拖动调整我的应用顺序</div>
      </div>
        <draggable  @end="end" v-model="myList">
          <transition-group class="cm-p-02 modify-block">
            <div class="modify-wrapper-bg"
                 v-for="(item,index) in myList"
                 :key="item.appName"
                 @click="goApp(item.homepageLink)"
            >
              <div class="cm-flex">
              <div class="modify-empty"></div>
              <div class="cm-tx-c">
                <div><img class="cm-img-08 cm-border-radius-10"
                          :src="item.appIcon"
                          alt=""></div>
              </div>
              <div class="modify-empty">
                <img :src="delIcon"
                     class="already-add-size"
                     @click.stop="changeSort('reduce',index,item)"
                >
              </div>
              </div>
              <div class="modify-label">{{item.appName}}</div>
            </div>
          </transition-group>
        </draggable>
    </div>
    <div v-for="(itemList,index1) in appList" class="cm-bc-white cm-mt-02" v-if="itemList.list.length>0">
      <div class="cm-flex cm-jc-sb cm-pt-02 cm-plr-02">
        <div class="cm-fs-030 cm-fw-bold">{{itemList.typeName}}</div>
      </div>
      <div class="cm-p-02" >
            <div :class="[isDrag? 'modify-wrapper-bg': 'modify-wrapper']"
                 v-for="(item,index) in itemList.list"
                 @click="goApp(item.homepageLink)"
            >
              <div class="cm-flex">
              <div class="modify-empty"></div>
              <div class="cm-tx-c">
                <div><img class="cm-img-08 cm-border-radius-10"
                          :src="item.appIcon"
                          alt=""></div>
              </div>
              <div class="modify-empty">
                <img :src="addIcon" class="already-add-size" alt=""
                     v-if="isDrag && !item.selected"
                     @click.stop="changeSort('add',index,item)"
                >
                <img :src="alreadyAdd"
                     class="already-add-size"
                     alt=""
                     v-if="isDrag && item.selected">
              </div>
              </div>
              <div class="modify-label">{{item.appName}}</div>
            </div>
      </div>
    </div>
    <div><img class="modify-bottom" :src="bottomObj.bgImg" alt=""></div>
  </div>
</template>
  1. 编写逻辑。
created(){
      self = this;
      var promise1 = new Promise(function (resolve) {
        self.getAppList(function (res) {
          resolve(res);
        });
      });
      var promise2 = new Promise(function (resolve) {
        self.getAppTypeList(function (res) {
          resolve(res);
        });
      });
      var promise3 = new Promise(function (resolve) {
        self.getMyList(function (res) {
          resolve(res);
        });
      });
      var pro = Promise.all([promise1,promise2,promise3]);
      pro.then(function ([list,typeList,myList]) {
        self.loading = false;
        self.typeList = typeList;
        self.allList = list;
        //其他应用中包含我的应用时,修改selected状态为true
        console.log(list);
        console.log(myList);
        list.map((item,index)=>{

          for (var k = 0; k < myList.length; k++) {
             if(item.appName === myList[k].appName){
               item.selected = true;
             }
          }
        });
        for (var i = 0; i < typeList.length; i++){
          var item = typeList[i];
          self.typeList[i].list = [];
          for (var j = 0; j < list.length; j++) {
            if (item.id == list[j].typeId) {
              self.typeList[i].list.push(list[j]);
            }
          }
        }
        self.appList = self.typeList;
      })
    },

    methods: {
        end(){
          self.$forceUpdate();
        },
       goBack:()=>{
         self.$router.push({name: "home"});
       },
      cancel(){
        self.isDrag = !self.isDrag;
      },
      goApp(url){
        dd.biz.util.openLink({
          url:url,//要打开链接的地址
          onSuccess : function(result) {
            /**/
          },
          onFail : function(err) {}
        });
      },
      changeSort: (str,index,item) => {
        var arr = self.myList;
        console.log(item);
        //如果点击的是删除按钮
        if (str == 'reduce') {
          if (arr.length <= self.minNum) {
            //常用应用个数小于或等于3则弹出提示框
            self.$message.error('自建应用不能少于'+self.minNum+'个');
          } else {
            //常用应用个数大于3才能删除
            self.myList.splice(index, 1);
            if(item.selected){
              item.selected = !item.selected;
            }
            self.allList.map((item1,index)=>{
                if(item1.appName === item.appName){
                  item1.selected = false;
                }
            });
            self.$forceUpdate();
          }
        } else {
          //如果点击的是添加按钮
          if (arr.length >= self.maxNum) {
            //添加时如果大于或等于11个应用时,则弹出提示框
            self.$message.error('自建应用不能多于'+self.maxNum+'个');
          } else {
            arr.push(item);
            item.selected = true;
          }
        }
      },
      displayOperate: (operate) => {
        //判断是否显示编辑按钮,编辑按钮在第一行显示
        self.isDrag = !self.isDrag;
        var data = [];
        self.myList.map((item,index)=>{
          data.push({"agentId":item.agentId,"orderId":index})
        });
        console.log(data);
        if(operate == 'done'){
          getData({
            method: 'post',
            url: 'appInfo/addUserAppList',
            data:{
              "appList": data
            },
            successCB: (res) => {
              //cb(res.result);
            }
          });
        }
      },
      getAppList: (cb) => {
        getData({
          method: 'post',
          url: 'appInfo/getappList',
          data:{
            pageCount: 1,
            pageSize: 200
          },
          successCB: (res) => {
            cb(res.result);
          }
        });
      },
      getMyList: (cb) => {
        getData({
          method: 'post',
          url: 'appInfo/getappListForHome',
          data:{},
          successCB: (res) => {
            self.myList = res.result;
            cb(res.result);
          }
        });
      },
      getAppTypeList(cb){
        getData({
          method: 'post',
          url: 'appInfo/getappTypeList',
          data:{
            pageCount: 1,
            pageSize: 200
          },
          successCB: (res) => {
            console.log(res);
            cb(res.result);
          }
        });
      }
    }

三、效果

以下是将常用应用的“应用10”和"应用11"删除,将生活娱乐中的"应用111"和"应用112"添加到常用应用中。
在这里插入图片描述

四、总结

  1. 这个功能的重点是先要封装数据结构,处理成二维数组的形式。
  2. 数据结构清晰之后,如果是删除,则通过 splice 来删除数组中的对象;如果是添加,则通过 push 将对象添加到数组中。
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
好的,下面是一个简单的 Vue 实现 todolist 的添加删除功能的代码示例: ```html <!DOCTYPE html> <html> <head> <title>Vue TodoList</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <h1>TodoList</h1> <input type="text" v-model="newTodo"> <button @click="addTodo">Add</button> <ul> <li v-for="(todo, index) in todos"> {{ todo }} <button @click="removeTodo(index)">Delete</button> </li> </ul> </div> <script> var app = new Vue({ el: '#app', data: { newTodo: '', todos: [] }, methods: { addTodo: function() { if (this.newTodo != '') { this.todos.push(this.newTodo); this.newTodo = ''; } }, removeTodo: function(index) { this.todos.splice(index, 1); } } }) </script> </body> </html> ``` 在这个示例中,我们首先定义了一个包含两个属性的 Vue 实例,分别是 `newTodo` 和 `todos`。`newTodo` 表示用户输入的待办事项,`todos` 表示所有已添加的待办事项列表。 然后,我们定义了两个方法,`addTodo` 和 `removeTodo`,来实现添加删除待办事项的功能。在 `addTodo` 方法中,我们首先判断用户输入的待办事项是否为空,如果不为空,则将其添加到 `todos` 列表中,并清空 `newTodo`。在 `removeTodo` 方法中,我们通过 `splice` 方法从 `todos` 列表中删除指定索引的待办事项。 最后,我们在页面中使用 `v-model` 指令绑定用户输入的待办事项到 `newTodo` 属性上,使用 `v-for` 指令循环渲染 `todos` 列表,并在每个待办事项后面添加一个删除按钮,通过 `@click` 绑定 `removeTodo` 方法来实现删除功能
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值