Vue3和flask的前后端管理员增删改查(实验项目第七期)

管理员的增删改查

前端路由守卫

首先需要在router/index.js里写管理员页面的路由守卫:

{
    path: '/admin',
    name: 'admin',
    component: () => import('@/views/Admin/admin_index.vue'),
    // 添加路由守卫
    beforeEnter: (to, from, next) => {
        const privilege = localStorage.getItem('privilege')
        if (privilege === '100') {		//检测privilege为100的才是管理员
            next()
        } else {
            next('/')  // 如果没有管理员权限,跳转到登录页面
        }
    }
},

然后我们整个管理员页面采用组件化的思维搭建,如下图:

--Admin
----components
--------admin_filtdata.vue
--------admin_traindata.vue
--------admin_user.vue
----admin_index.vue

将components里的三个组件全部加载到管理员的默认页面admin_index.vue里

<template>
  <div>
    <el-row class="tac">
      <el-col :span="3">
        <h5 class="mb-2">管理选项</h5>
        <el-menu
          default-active="2"
          class="el-menu-vertical-demo"
          @open="handleOpen"
          @close="handleClose"
        >
          <!-- 1、用户管理 -->
          <el-sub-menu index="1">
            <template #title>
              <el-icon><User /></el-icon>
              <span>用户管理</span>
            </template>
            <el-menu-item index="1-1" @click="handleMenuItemClick('adminUser')">
              <el-icon><Edit /></el-icon>
              增删改查
            </el-menu-item>
          </el-sub-menu>

          <!-- 2、数据处理 -->
          <el-sub-menu index="2">
            <template #title>
              <el-icon><Files /></el-icon>
              <span>数据处理</span>
            </template>
            <el-menu-item index="2-1" @click="handleMenuItemClick('adminFiltData')">
              <el-icon><el-icon-download /></el-icon>
              清洗数据
            </el-menu-item>
          </el-sub-menu>

          <!-- 3、数据导入 -->
          <el-sub-menu index="3">
            <template #title>
              <el-icon><UploadFilled /></el-icon>
              <span>数据导入</span>
            </template>
            <el-menu-item index="3-1" @click="handleMenuItemClick('adminTrainData')">
              <el-icon><el-icon-upload/></el-icon>
              模型更新
            </el-menu-item>
          </el-sub-menu>

      <el-col :span="21">
        <div class="main-content">
          <div class="page-header">
            <h1>欢迎管理员</h1>
          </div>
          <div class="page-content">
            <AdminUser v-if="activeTab === 'users'" />
            <AdminTrainData v-if="activeTab === 'importData'" />
            <AdminFiltData v-if="activeTab==='filtData'" />
          </div>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script>

import AdminUser from "@/views/Admin/components/admin_user.vue";
import AdminFiltData from "@/views/Admin/components/admin_filtdata.vue";
import AdminTrainData from "@/views/Admin/components/admin_traindata.vue";


export default {
  data() {
    return {
      activeTab: 'users', // 默认显示用户管理组件
    };
  },
  components: {
    AdminUser,
    AdminFiltData,
    AdminTrainData,
  },
  methods: {
    handleOpen(key, keyPath) {
      console.log(key, keyPath);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    },
    handleMenuItemClick(which) {
      // 根据点击的菜单项加载对应的组件
      if (which === 'adminUser') {
        this.activeTab = 'users';
      } 
      else if(which === 'adminFiltData' ){
        this.activeTab = 'filtData';
      }
      else if (which === 'adminTrainData') {
        this.activeTab = 'importData';
      }
    },
  },
}
</script>

请注意,此处使用了element-plus组件代替style的效果,我采用的是vite[按需引入]element-plus所以可以直接使用,请根据自己的实际情况引入

后端蓝图接口

开一个蓝图,下面放所有管理员功能需要的接口

from flask import Blueprint

bp_admin = Blueprint('admin_bp', __name__)



1、获取用户数据、查找用户

分页查询种类:

真分页

每次翻页从数据库里查询数据

优点:不容易造成内存溢出

缺点:实现复杂、性能相对低
接下来是真分页的代码(真分页是我做另一个考试项目的时候做的):
这里附带了[模糊匹配]的题目查找功能,并且我的axios实例附带了response响应拦截器,所以不需要.catch(error => {…})

前端代码
<template>
	  <!-- 查找题目input框 省略-->
	  
	  <!-- data属性绑定了要显示的用户数据 -->
      <el-table :data="currentPageQuestions" >    
        <el-table-column prop="id" label="题目ID"></el-table-column>
        <el-table-column prop="question" label="题目"></el-table-column>
        <el-table-column prop="A" label="选项A"></el-table-column>
        <el-table-column prop="B" label="选项B"></el-table-column>
        <el-table-column prop="C" label="选项C"></el-table-column>
        <el-table-column prop="D" label="选项D"></el-table-column>
        <el-table-column prop="answer" label="答案"></el-table-column>
        <el-table-column prop="chosen" label="是否被选用"></el-table-column>
        <el-table-column label="操作">
            <!-- #default 指令来定义作用域插槽(允许在模板中访问父组件传给子组件的数据),再用 scope.row 来访问当前行的数据对象-->
          <template #default="scope">   
            <el-button type="primary" size="small" @click="confirmDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页码列表 -->
      <el-pagination background  
          @current-change="handlePageChange($event)"
          :current-page="currentPage"
          :page-size="pageSize"
          :total="total" 
        ></el-pagination>
        
</template>
<script>
  import axios from '@/utils/http.js';

export default{
    data() {
        return{
	        searchform:{		//用于查找题目
	                question:''
	        },
            currentPage: 1,   //当前页码
            pageSize: 10,     //每页条目数

            total: 0,                   //存储后端返回的题目总数
            currentPageQuestions: [] ,     // 当前用于展示的题目数据!
            }
    },
    methods:{
        //1、获取单选题库数据(真分页)
        getSingleQuestion(){
            this.pageSize = 10;         //把每页显示条目数固定为10
            axios.get('/admin/get_single_questions',{
                params:{ 
                    page: this.currentPage,   //查询时起点为第当前页码
                    per_page: this.pageSize  //查询时每页的条目数(默认为10)
                }
            }).then(response =>{
                this.currentPageQuestions = response.data.questions;
                this.total = response.data.total_questions;
            })
        },
        // 分页码列表API(监听页码变化,更新当前页码并获取对应的用户数据)
        handlePageChange(newPage) {
            this.currentPage = newPage;
            this.getSingleQuestion();
        },
        //2、查找题目
        searchSingleQ(){
            this.pageSize = 100;    //把每页显示条目数拉大
            axios.post('/admin/search_single_question',{
                question:this.searchform.question,
            })
            .then(response => {
            console.log(response.data.message);
            //将找到的所有用户显示(赋值给currentPageUsers列表)
            if(response.data.status === 'success'){
                this.currentPageQuestions = response.data.questions;
                this.total = response.data.total_questions;
                this.$message.success('查找单选题成功');
                }
            })
        },
    },
    //钩子函数(真分页)
    created(){
        this.getSingleQuestion();
    },

  }

</script>
后端代码
from flask import Blueprint,jsonify,session,request
from extendsions import db
from function import verify_token
from function.decorators import check_admin_privilege
from model.single_qbank import Single_qbank

Admin_single_qbank_bp = Blueprint("Admin_single_qbank",__name__)

#检查管理员的前端请求的合法性
def test_admin_token():
    # 解码请求头里的token检验session里的uid
    if (verify_token.test(request)):
        print("token合法正确! verify right!")
        return True
    else:
        print("登录凭证失效,请重新登录!")
        return False

#admin的蓝图url前面全部带上了'/admin'
#功能1、分页获取单选题库(真分页)
@Admin_single_qbank_bp.route('/get_single_questions',methods=['GET'])
@check_admin_privilege  # 装饰器检查管理员权限
def admin_get_single_questions():
    # 调用全局函数,检查管理员的前端请求token凭证
    if (test_admin_token() == False):
        response = {
            'status': 'error',
            'message': '登录凭证失效,请重新登录'
        }
        return jsonify(response), 403
    try:
        current_page = int(request.args.get('page'))  #当前页码(记得转换为int类型,paginate参数不接受str)
        per_page = int(request.args.get('per_page')) #一页多少条数
        single_questions = Single_qbank.query.all()
        total_questions = len(single_questions) #题库总数
        pagination = Single_qbank.query.paginate(page=current_page, per_page=per_page, error_out=False)   #error_out页数超出范围会抛出异常,设置为 False 则不会抛出异常
        questions = pagination.items    #分页出来的内容放入questions传回前端
        #定义一个response
        response = {
            'status': 'success',
            'message': '成功获取单选题库',
            'questions': [],
            'total_questions': total_questions
        }
        #把questions里的值都放入response的列表里
        for question in questions:
            response['questions'].append({
                'id': question.id,
                'question': question.question,
                'A': question.A,
                'B': question.B,
                'C': question.C,
                'D': question.D,
                'answer': question.answer,
                'chosen': question.chosen
            })
        return jsonify(response),200
    except Exception as e:
        response = {
            'status': 'error',
            'message': f'获取单选题库失败:{str(e)}'
        }
        return jsonify(response), 500

#功能2、查找单选题(模糊查找)
@Admin_single_qbank_bp.route('/search_single_question',methods=['POST'])
@check_admin_privilege  # 装饰器检查管理员权限
def admin_search_single_question():
    # 调用全局函数,检查管理员的前端请求token凭证
    if (test_admin_token() == False):
        response = {
            'status': 'error',
            'message': '登录凭证失效,请重新登录'
        }
        return jsonify(response), 403
    try:
        data = request.get_json()
        question = data.get('question')
        #使用like()方法进行模糊查找,% 表示通配符,匹配任意字符,返回所有查询结果
        results = Single_qbank.query.filter(Single_qbank.question.like(f'%{question}%')).all()
        #查询结果总数量
        counts = Single_qbank.query.filter(Single_qbank.question.like(f'%{question}%')).count()
        # 定义一个response
        response = {
            'status': 'success',
            'message': '成功获取单选题库',
            'questions': [],
            'total_questions': counts
        }
        #把results里的值都放入response的列表里
        for result in results:
            response['questions'].append({
                'id': result.id,
                'question': result.question,
                'A': result.A,
                'B': result.B,
                'C': result.C,
                'D': result.D,
                'answer': result.answer,
                'chosen': result.chosen
            })
        return jsonify(response), 200

    except Exception as e:
        response = {
            'status': 'error',
            'message': f'没有找到题目:{str(e)}'
        }
        return jsonify(response), 404

假分页

一次性查询所有数据存入内存,翻页时从内存里找

优点:实现简单、性能相对高

缺点:容易造成内存溢出

接下来是假分页的代码:

前端代码

显示数据:直接从后端将查询到的所有用户数据存入users列表里,然后翻页的时候查找对应页码的放入currentPageUsers用于在el-table里显示

查找用户:向后端传一个用户名字,然后找到这个用户直接传回前端赋值给currentPageUsers显示

 <template>
	<h2 class="title" >管理员页面</h2>
      <el-form :model="searchform" ref="form" label-width="80px">
        <el-form-item >
          <el-input v-model="searchform.username"  placeholder="输入用户名进行查找"></el-input>
          <el-button type="primary"  @click="searchUser" >查询用户</el-button>
          <el-button type="primary"  @click="addUser" >添加用户</el-button>
        </el-form-item>
      </el-form>
	<!-- data属性绑定了要显示的用户数据 -->
      <el-table :data="currentPageUsers" >    
        <el-table-column prop="uid" label="用户ID"></el-table-column>
        <el-table-column prop="username" label="用户名"></el-table-column>
        <el-table-column prop="email" label="用户邮箱"></el-table-column>
        <el-table-column label="操作">
          <template #default="scope">
            <el-button type="primary" size="small" @click="handleEdit(scope.row)">修改</el-button>
            <el-button type="primary" size="small" @click="confirmDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

        <!-- 分页码列表 -->
        <el-pagination background  
          @current-change="handlePageChange($event)"
          :current-page="currentPage"
          :page-size="pageSize"
          :total="total" 
        ></el-pagination>
 </template>
<script>
  import axios from '@/main.js';
  
  export default {
    data() {
      return {
        //输入用户名进行查找
        searchform: {
          username: ''
        },
        currentPage: 1,   //当前页码
        pageSize: 10,     //每页页数
        users: [],      //存储后端返回的全部用户数据
        total: 0,       //存储后端返回的用户总数
        currentPageUsers: [] ,     // 当前用于展示的用户数据!
      }
    },
    methods: {
      //1、获取用户数据
      getUser(){
        axios.get('/admin/user_get',{
          params:{  //(在假分页方式中舍去,不需要用到)
            page: 1,   //查询时起点为第1页
            per_page: 10   //查询时每页的条目数
          }
        }).then(res =>{
          this.users = res.data.users;        //后端查询的所有用户数据列表
          this.total = res.data.total_users;  //后端一共查询到多少条数据
          // 更新当前页码对应的用户数据
          this.updateCurrentPageUsers();
        }).catch(err=>{
          console.log(err);
        });
      },
      // 监听页码变化,更新当前页码并获取对应的用户数据
      handlePageChange(newPage) {
        this.currentPage = newPage;
        this.updateCurrentPageUsers();
      },
      // 根据当前页码获取对应的用户数据
      updateCurrentPageUsers() {
        const startIndex = (this.currentPage - 1) * this.pageSize;
        let endIndex = startIndex + this.pageSize;

        // 判断 endIndex 是否超出 users 数组的长度,如果超出则将其设置为 users 数组的长度
        if (endIndex > this.users.length) {
          endIndex = this.users.length;
        }
        this.currentPageUsers = this.users.slice(startIndex, endIndex);
      },
      //2、查找用户
      searchUser(){
        axios.post('/admin/user_search',{
          username:this.searchform.username
        })
        .then(response => {
          console.log(response.data.message);
          //将找到的用户显示(赋值给currentPageUsers列表)
          if(response.data.status === 'success'){
            this.currentPageUsers = [response.data.search_user]
            this.$message.success('查找用户成功');
          }
        })
        .catch(error => {
          this.$message.error('未找到该用户');
          console.log(error);
        })
      },
    //钩子函数,页面加载时触发,查询所有用户数据(假分页)
    created(){
      this.getUser();
    }
  }
  </script>
后端代码

做一个管理员权限检查装饰器(使用session会话实现)
(其实也可以使用JWT技术,每次去解码前端请求头中的token检查权限)

def check_admin_privilege(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if session.get('privilege') == 100:
            return func(*args, **kwargs)
        else:
            return jsonify({
                'status': 'fail',
                'message': '您不是管理员,没有权限进行此操作'
            }),403
    return wrapper
 
#蓝图开接口
@bp_admin.route('/admin/user_get', methods=['GET'])
# 使用装饰器检查是否有管理员权限
@check_admin_privilege
# 管理员功能1:通过查询数据库来获取用户表中的数据,并将其转换成字典形式后返回给前端。
def get_users():
    users = User.query.all()    #查询所有用户数据,传给前端
    total_users = len(users)    #一共有多少条数据
    user_list = []      #列表,用户存储全部用户数据
    for user in users:
        user_data = {
            'uid': user.uid,
            'username': user.username,
            'email': user.email
        }
        user_list.append(user_data)
    response = {
        'status': 'success',
        'message': '获取成功',
        'users' : user_list,
        'total_users':total_users
    }
    return jsonify(response),200
    
# 管理员功能2:查找用户
#省略...



2、增加、修改、删除用户

前端

有了前面的用户显示、查询的铺垫,后面三个功能就好做多了(三个功能大同小异)
我们这里增加、修改都采用弹窗:

  <template>
		<!-- 添加用户弹窗 -->
        <el-dialog v-model="addDialogVisible" title="添加用户">
          <el-form :model="addForm" ref="addForm" :rules="addFormRules" label-width="80px">
            <el-form-item label="用户名" prop="username">
              <el-input v-model="addForm.username"></el-input>
            </el-form-item>
            <el-form-item label="用户密码" prop="password">
              <el-input v-model="addForm.password"></el-input>
            </el-form-item>
            <el-form-item label="用户邮箱" prop="email">
              <el-input v-model="addForm.email"></el-input>
            </el-form-item>
          </el-form>
          <template #footer>
            <span class="dialog-footer">
              <el-button @click="addDialogVisible = false">取消</el-button>
              <el-button type="primary" @click="addUserSubmit">确定</el-button>
            </span>
          </template>
        </el-dialog>
        <!-- 修改用户弹窗 -->
        //修改用户弹窗 省略....
  </template>
<script>
import axios from '@/main.js';  

export default {
    data() {
      return {
        addDialogVisible: false,
        editDialogVisible: false,
        addForm:{
          username: '',
          password: '',
          email: ''
        },
        editForm: {
          uid: '',
          username: '',
          password: '',
          email: ''
        },
        addFormRules: {
          username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
          password: [{ required: true, message: '请输入用户密码', trigger: 'blur' }],
          email: [{ required: true, message: '请输入用户邮箱', trigger: 'blur' }]
        },
        editFormRules: {
          username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
          email: [{ required: true, message: '请输入用户邮箱', trigger: 'blur' }]
        }
      }
    },
    methods: {
      //3、添加用户数据
      addUser(){
        this.addDialogVisible = true;
      },
      addUserSubmit(){
      	//valid表示满足表单rules以后才能执行
        this.$refs.addForm.validate(valid =>{
          if(valid){
            axios.post('/admin/user_add',{
              username:this.addForm.username,
              password:this.addForm.password,
              email:this.addForm.email
              }).then(res => {
                this.$message.success('添加用户成功');
                this.getUser();
                this.addDialogVisible = false;
              }).catch(err => {
                console.log(err);
              });
          } else{
            return false;
          }
        });
      },
      //修改用户省略....
    }
}
</script>

而删除用户则直接采用函数弹窗的形式:

//5、删除用户数据
      confirmDelete(row) {
        this.$confirm(`确定要删除用户${row.username}吗?`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          axios.delete('admin/user_delete',{
            //params 对象表示请求的查询参数,将要删除的用户的 uid 作为参数传递给后端。
            params: {
              uid: row.uid
            }
          }
          ).then(res => {
            this.$message.success('删除用户成功');
            this.getUser();
          }).catch(err => {
            console.log(err);
          });
        }).catch(() => {});
      },

后端

增加、修改、删除,会一个就会全部

# 管理员功能4:修改用户
@bp_admin.route('/admin/user_update',methods=['PUT'])
@check_admin_privilege
def update_user():
    data = request.get_json()
    user_id = data.get('uid')
    user = User.query.filter_by(uid = user_id).first()
    if 'username' in data:
        user.username = data.get('username')
    if 'password' in data:
        user.password = data.get('password')
    if 'email' in data:
        user.email = data.get('email')
    try:
        db.session.commit()
    except Exception:
        print("update error")
        return '',400
    return jsonify(user.to_dict()),200

请求方法(GET,POST,PUT,DELETE)

请特别注意:
post,put是有请求体的
前端可以写:

axios.put('admin/user_update', {
	//内容
     uid:this.uid,
}

后端的获取数据逻辑为:

data = request.get_json()
user_id = data.get('uid')

但是get,delete一般是没有请求体的,后端无法读request的body
前端逻辑是这样的:(放在查询参数params里)

axios.delete('admin/user_delete',{
    //params 对象表示请求的查询参数,将要删除的用户的 uid 作为参数传递给后端。
    params: {
      uid: row.uid
    }
  }

后端接收逻辑为:

#从request的params里取数据
user_id = request.args.get('uid')



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
前后端分离的实现方式有很多种,以下是一种基于 FlaskVue.js 的实现方式: 1. 后端使用 Flask 框架搭建 API,可以使用 Flask-RESTful 库来方便地实现 RESTful API。例如: ```python from flask import Flask, jsonify, request from flask_cors import CORS app = Flask(__name__) CORS(app) tasks = [ { 'id': 1, 'title': 'Task 1', 'description': 'This is task 1', 'done': False }, { 'id': 2, 'title': 'Task 2', 'description': 'This is task 2', 'done': False } ] @app.route('/tasks', methods=['GET']) def get_tasks(): return jsonify({'tasks': tasks}) @app.route('/tasks/<int:task_id>', methods=['GET']) def get_task(task_id): task = [task for task in tasks if task['id'] == task_id] if len(task) == 0: abort(404) return jsonify({'task': task[0]}) @app.route('/tasks', methods=['POST']) def create_task(): if not request.json or not 'title' in request.json: abort(400) task = { 'id': tasks[-1]['id'] + 1, 'title': request.json['title'], 'description': request.json.get('description', ''), 'done': False } tasks.append(task) return jsonify({'task': task}), 201 @app.route('/tasks/<int:task_id>', methods=['PUT']) def update_task(task_id): task = [task for task in tasks if task['id'] == task_id] if len(task) == 0: abort(404) if not request.json: abort(400) task[0]['title'] = request.json.get('title', task[0]['title']) task[0]['description'] = request.json.get('description', task[0]['description']) task[0]['done'] = request.json.get('done', task[0]['done']) return jsonify({'task': task[0]}) @app.route('/tasks/<int:task_id>', methods=['DELETE']) def delete_task(task_id): task = [task for task in tasks if task['id'] == task_id] if len(task) == 0: abort(404) tasks.remove(task[0]) return jsonify({'result': True}) if __name__ == '__main__': app.run(debug=True) ``` 2. 前端使用 Vue.js 框架搭建页面,通过 AJAX 调用后端提供的 API 来实现增删改查功能。例如: ```html <!DOCTYPE html> <html> <head> <title>Tasks</title> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> </head> <body> <div id="app"> <v-app> <v-container> <v-text-field label="Title" v-model="title"></v-text-field> <v-text-field label="Description" v-model="description"></v-text-field> <v-btn color="primary" @click="createTask">Create</v-btn> <v-data-table :headers="headers" :items="tasks" :search="search" item-key="id"> <template v-slot:top> <v-toolbar flat> <v-toolbar-title>Tasks</v-toolbar-title> <v-spacer></v-spacer> <v-text-field v-model="search" append-icon="search" label="Search"></v-text-field> </v-toolbar> </template> <template v-slot:item.actions="{ item }"> <v-icon small class="mr-2" @click="editTask(item)">edit</v-icon> <v-icon small @click="deleteTask(item)">delete</v-icon> </template> </v-data-table> <v-dialog v-model="dialog" persistent max-width="600px"> <v-card> <v-card-title> <span class="headline">{{ formTitle }}</span> </v-card-title> <v-card-text> <v-text-field label="Title" v-model="editedTask.title"></v-text-field> <v-text-field label="Description" v-model="editedTask.description"></v-text-field> </v-card-text> <v-card-actions> <v-spacer></v-spacer> <v-btn color="blue darken-1" text @click="closeDialog">Cancel</v-btn> <v-btn color="blue darken-1" text @click="saveTask">Save</v-btn> </v-card-actions> </v-card> </v-dialog> </v-container> </v-app> </div> <script> new Vue({ el: '#app', data: { title: '', description: '', headers: [ { text: 'ID', value: 'id' }, { text: 'Title', value: 'title' }, { text: 'Description', value: 'description' }, { text: 'Done', value: 'done' }, { text: 'Actions', value: 'actions' } ], tasks: [], search: '', dialog: false, formTitle: '', editedTask: { id: 0, title: '', description: '', done: false } }, created: function () { this.fetchTasks(); }, methods: { fetchTasks: function () { axios.get('/tasks') .then(response => { this.tasks = response.data.tasks; }) .catch(error => { console.log(error); }); }, createTask: function () { axios.post('/tasks', { title: this.title, description: this.description }) .then(response => { this.tasks.push(response.data.task); this.title = ''; this.description = ''; }) .catch(error => { console.log(error); }); }, editTask: function (task) { this.formTitle = 'Edit Task'; this.editedTask = Object.assign({}, task); this.dialog = true; }, saveTask: function () { axios.put('/tasks/' + this.editedTask.id, { title: this.editedTask.title, description: this.editedTask.description, done: this.editedTask.done }) .then(response => { var index = this.tasks.findIndex(task => task.id == response.data.task.id); Vue.set(this.tasks, index, response.data.task); this.dialog = false; }) .catch(error => { console.log(error); }); }, deleteTask: function (task) { axios.delete('/tasks/' + task.id) .then(response => { var index = this.tasks.findIndex(t => t.id == task.id); this.tasks.splice(index, 1); }) .catch(error => { console.log(error); }); }, closeDialog: function () { this.dialog = false; setTimeout(() => { this.editedTask = { id: 0, title: '', description: '', done: false }; }, 300); } } }); </script> </body> </html> ``` 以上代码仅供参考,具体实现方式可以根据实际需求进行调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值