前端项目开发流程与前后端联调

目录

  • 1 前端项目开发流程
    • 1.1 项目开发流程
      • 1.1.1定义路由模块
      • 1.1.2 定义api模块
      • 1.1.3 定义页面组件脚本
      • 1.1.4 定义页面组件模板
    • 1.2项目执行流程
      • 1.2.1 页面加载流程
      • 1.2.2 页面渲染流程
  • 2 分页列表组件
    • 2.1 分页查询
      • 2.1.1 定义api模块
      • 2.1.2、定义页面组件脚本
      • 2.1.3、定义页面组件模板
      • 2.1.4、改变每页条数
      • 2.1.5 翻页
      • 2.1.6 序号列
      • 2.1.7 查询表单
    • 2.2 数据删除
      • 2.2.1、定义api模块
      • 2.2.2、定义页面组件模板
      • 2.2.3 定义页面组件脚本
    • 2.3 axios响应拦截器
      • 2.3.1、关于code===20000
      • 2.3.2、关于response
      • 2.3.3、关于error
  • 3 表单组件
    • 3.1 新增讲师
      • 3.1.1、定义api模块
      • 3.1.2 定义页面组件脚本
      • 3.1.3 定义页面组件模板
      • 3.1.4 实现新增功能
    • 3.2 显示讲师信息
      • 3.2.1 定义api模块
      • 3.2.2 定义页面组件脚本
      • 3.2.3、定义页面组件模板
    • 3.3 更新讲师
      • 3.3.1 定义api模块
      • 3.3.2、定义页面组件脚本
    • 3.4 组件重用问题
  • 4 关于计算属性
    • 例1:模板中使用js表达式
    • 例2:使用计算属性
    • 例3:使用方法
  • 5 关于Vue组件
    • 5.1 什么是组件
    • 5.2 前端项目组件分析
      • 5.2.1、三要素
      • 5.2.2、入口文件
      • 5.2.3、主页面模块
      • 5.2.4、路由模块
      • 5.2.5、登录页面组件
    • 5.3 前端项目布局分析
      • 5.3.1、路由模块
      • 5.3.2、布局模块
      • 5.3.3、核心内容区域
      • 5.3.4、讲师列表页面组件

1 前端项目开发流程

1.1 项目开发流程

前端项目开发流程与前后端联调_第1张图片

1.1.1定义路由模块

src/router/index.js

配置讲师管理相关路由

1.1.2 定义api模块

创建文件 src/api/teacher.js

前端请求接口定义,只是定义接口,不是实际调用,实际调用在,.vue文件中

// @ 符号在build/webpack.base.conf.js 中配置 表示 'src' 路径
import request from '@/utils/request'
export default {
  list() {
    return request({
      url: '/admin/edu/teacher/list',
      method: 'get'
    })
  }
}

1.1.3 定义页面组件脚本

src/views/teacher/list.vue

调用api获得数据

<script>
import teacherApi from '@/api/teacher'
export default {
  // 定义数据模型
  data() {
    return {
      list: [] // 讲师列表
    }
  },
  // 页面渲染成功后获取数据
  created() {
    this.fetchData()
  },
  // 定义方法
  methods: {
    fetchData() {
      // 调用api
      teacherApi.list().then(response => {
        this.list = response.data.items
      })
    }
  }
}
</script>

1.1.4 定义页面组件模板

数据做了一个:data="list"绑定,之后数据自动渲染到页面

<!-- 表格 -->
<el-table :data="list" border stripe>
    <el-table-column type="index" width="50"/>
    <el-table-column prop="name" label="名称" width="80" />
    <el-table-column label="头衔" width="90">
        <template slot-scope="scope">
          <el-tag v-if="scope.row.level === 1" type="success" size="mini">高级讲师</el-tag>
          <el-tag v-if="scope.row.level === 2" size="mini">首席讲师</el-tag>
        </template>
    </el-table-column>
    <el-table-column prop="intro" label="简介" />
    <el-table-column prop="sort" label="排序" width="60" />
    <el-table-column prop="joinDate" label="入驻时间" width="160" />
</el-table>

1.2项目执行流程

1.2.1 页面加载流程

前端项目开发流程与前后端联调_第2张图片

1.2.2 页面渲染流程

前端项目开发流程与前后端联调_第3张图片

2 分页列表组件

2.1 分页查询

2.1.1 定义api模块

src/api/teacher.js

get请求用 params传参,是键值对的形式,拼接到字符串后面

pageList(page, limit, searchObj) {
    return request({
        url: `/admin/edu/teacher/list/${page}/${limit}`,
        method: 'get',
        params: searchObj
    })
}

2.1.2、定义页面组件脚本

src/views/teacher/list.vue,完善data定义,之后将完整参数发送请求,最后回显数据

data() {// 定义数据
    return {
        list: null, // 数据列表
        total: 0, // 总记录数
        page: 1, // 页码
        limit: 10, // 每页记录数
        searchObj: {}// 查询条件
    }
}

修改fetchData方法

fetchData() {
    // 调用api
    teacherApi.pageList(this.page, this.limit, this.searchObj).then(response => {
        this.list = response.data.rows
        this.total = response.data.total
    })
}

2.1.3、定义页面组件模板

在table组件下面添加分页组件

<!-- 分页组件 -->
<el-pagination
  :current-page="page"
  :total="total"
  :page-size="limit"
  :page-sizes="[5, 10, 20, 30, 40, 50, 100]"
  style="padding: 30px 0; text-align: center;"
  layout="total, sizes, prev, pager, next, jumper"
/>

2.1.4、改变每页条数

为组件注册事件
前端项目开发流程与前后端联调_第4张图片

当注册时间有回调参数时不必要自己传入,也就是绑定的方法@size-change会自动注入一个参数,比如当前页,之后绑定方法的名字changePageSize可以不用传参,只需到时候调用随便给个参数名字之后就可以获得参数值,changePageSize(size),得到参数.这就好比回调函数的then中的response=>也不是自己创建的,到时候框架会自动获得.如果传入带()就成了方法调用,而不是方法引用框架就不会为我们获得参数,只是引用其中的方法.你传的东西啥事儿都干不了!

@size-change="changePageSize"

定义事件脚本

// 每页记录数改变,size:回调参数,表示当前选中的“每页条数”
changePageSize(size) {
    this.limit = size
    this.fetchData()
}

2.1.5 翻页

为组件注册事件

@current-change="changeCurrentPage"

定义事件脚本

// 改变页码,page:回调参数,表示当前选中的“页码”
changeCurrentPage(page) {
    this.page = page
    this.fetchData()
},  

2.1.6 序号列

这里是防止到了第二页显示还是 1 2 3 4 这样的序号,然后会变为5 6 7 8

<el-table-column
  label="#"
  width="50">
  <template slot-scope="scope">
    {{ (page - 1) * limit + scope.$index + 1 }}
  </template>
</el-table-column>

2.1.7 查询表单

在table组件上面添加查询表单

<!--查询表单-->
<el-form :inline="true">
    <el-form-item>
        <el-input v-model="searchObj.name" placeholder="讲师"/>
    </el-form-item>
    <el-form-item>
        <el-select v-model="searchObj.level" clearable placeholder="头衔">
            <el-option value="1" label="高级讲师"/>
            <el-option value="2" label="首席讲师"/>
        </el-select>
    </el-form-item>
    <el-form-item label="入驻时间">
        <el-date-picker
                        v-model="searchObj.joinDateBegin"
                        placeholder="开始时间"
                        value-format="yyyy-MM-dd" />
    </el-form-item>
    <el-form-item label="-">
        <el-date-picker
                        v-model="searchObj.joinDateEnd"
                        placeholder="结束时间"
                        value-format="yyyy-MM-dd" />
    </el-form-item>
    <el-form-item>
        <el-button type="primary" icon="el-icon-search" @click="fetchData()">查询</el-button>
        <el-button type="default" @click="resetData()">清空</el-button>
    </el-form-item>
</el-form>

重置表单脚本

// 重置表单
resetData() {
    this.searchObj = {}
    this.fetchData()
}

2.2 数据删除

2.2.1、定义api模块

src/api/teacher.js

removeById(id) {
    return request({
        url: `/admin/edu/teacher/remove/${id}`,
        method: 'delete'
    })
}

2.2.2、定义页面组件模板

在table组件中添加删除列

<el-table-column label="操作" width="200" align="center">
    <template slot-scope="scope">
        <el-button type="danger" size="mini" icon="el-icon-delete" @click="removeById(scope.row.id)">删除</el-button>
    </template>
</el-table-column>

2.2.3 定义页面组件脚本

// 根据id删除数据
removeById(id) {
    this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
        return teacherApi.removeById(id)
    }).then((response) => {
        this.fetchData()
        this.$message.success(response.message)
    }).catch(error => {
        console.log('error', error)
        // 当取消时会进入catch语句:error = 'cancel'
        // 当后端服务抛出异常时:error = 'error'
        if (error === 'cancel') {
            this.$message.info('取消删除')
        }
    })
}

2.3 axios响应拦截器

2.3.1、关于code===20000

code!==20000的响应会被拦截,并转到 error=>{} 处理

if (res.code !== 20000) {
    return Promise.reject('error')
}

2.3.2、关于response

code===20000时放行,前端页面接收到response.data的值,而不是response

if (res.code !== 20000) {
    return Promise.reject('error')
} else {
    return response.data
}

2.3.3、关于error

统一处理错误结果,显示错误消息

3 表单组件

3.1 新增讲师

3.1.1、定义api模块

如果是get请求传递键值对的话是param进行传参,如果后台需要json数据的话用data进行传参

src/api/teacher.js

save(teacher) {
    return request({
        url: '/admin/edu/teacher/save',
        method: 'post',
        data: teacher
    })
}

3.1.2 定义页面组件脚本

src/views/teacher/form.vue,完善data定义

<script>
export default {
  data() {
    return {
      // 初始化讲师默认数据
      teacher: {
        sort: 0,
        level: 1
      },
      saveBtnDisabled: false // 保存按钮是否禁用,防止表单重复提交
    }
  }
}
</script>

3.1.3 定义页面组件模板

src/views/teacher/form.vue


<el-form label-width="120px">
    <el-form-item label="讲师名称">
        <el-input v-model="teacher.name" />
    el-form-item>
    <el-form-item label="入驻时间">
        <el-date-picker v-model="teacher.joinDate" value-format="yyyy-MM-dd" />
    el-form-item>
    <el-form-item label="讲师排序">
        <el-input-number v-model="teacher.sort" :min="0"/>
    el-form-item>
    <el-form-item label="讲师头衔">
        <el-select v-model="teacher.level">
            
            <el-option :value="1" label="高级讲师"/>
            <el-option :value="2" label="首席讲师"/>
        el-select>
    el-form-item>
    <el-form-item label="讲师简介">
        <el-input v-model="teacher.intro"/>
    el-form-item>
    <el-form-item label="讲师资历">
       <el-input v-model="teacher.career" :rows="10" type="textarea"/>
    el-form-item>
    
    <el-form-item>
        <el-button :disabled="saveBtnDisabled" type="primary" @click="saveOrUpdate()">保存el-button>
    el-form-item>
el-form>

3.1.4 实现新增功能

src/views/teacher/form.vue,引入teacher api模块:

import teacherApi from '@/api/teacher'

定义保存方法

methods: {
  saveOrUpdate() {
    // 禁用保存按钮
    this.saveBtnDisabled = true
    this.saveData()
  },
  // 新增讲师
  saveData() {
    // debugger
    teacherApi.save(this.teacher).then(response => {
      this.$message({
        type: 'success',
        message: response.message
      })
      this.$router.push({ path: '/teacher' })
    })
  }
}

3.2 显示讲师信息

3.2.1 定义api模块

src/api/teacher.js

getById(id) {
    return request({
        url: `/admin/edu/teacher/get/${id}`,
        method: 'get'
    })
}

3.2.2 定义页面组件脚本

src/views/teacher/form.vue,methods中定义回显方法

// 根据id查询记录
fetchDataById(id) {
    teacherApi.getById(id).then(response => {
        this.teacher = response.data.item
    })
}

页面渲染成功后获取数据

因为已在路由中定义如下内容:path: ‘edit/:id’,因此可以使用 this.$route.params.id 获取路由中的id

//页面渲染成功
created() {
    if (this.$route.params.id) {
        this.fetchDataById(this.$route.params.id)
    }
}

3.2.3、定义页面组件模板

src/views/teacher/list.vue,表格“操作”列中增加“修改”按钮


    修改

3.3 更新讲师

3.3.1 定义api模块

src/api/teacher.js

updateById(teacher) {
    return request({
        url: '/admin/edu/teacher/update',
        method: 'put',
        data: teacher
    })
}

3.3.2、定义页面组件脚本

src/views/teacher/form.vue,methods中定义updateData

// 根据id更新记录
updateData() {
  // teacher数据的获取
  teacherApi.updateById(this.teacher).then(response => {
      this.$message({
        type: 'success',
        message: response.message
      })
      this.$router.push({ path: '/teacher' })
  })
},

完善saveOrUpdate方法

saveOrUpdate() {
    // 禁用保存按钮
    this.saveBtnDisabled = true
    if (!this.teacher.id) {
        this.saveData()
    } else {
        this.updateData()
    }
}

3.4 组件重用问题

**问题:**vue-router导航切换 时,如果两个路由都渲染同个组件,

组件的生命周期方法(created或者mounted)不会再被调用, 组件会被重用,显示上一个路由渲染出来的自建

**解决方案:**可以简单的在 router-view上加上一个唯一的key,来保证路由切换时都会重新触发生命周期方法,确保组件被重新初始化。

修改 src/views/layout/components/AppMain.vue 文件如下:


computed: {
    key() {
        return this.$route.name !== undefined? this.$route.name + +new Date(): this.$route + +new Date()
    }
 }

4 关于计算属性

解决:组件重用问题 每使用一次数学都会重新计算,而方法会从本地上次计算好的重新取出来.

前端项目开发流程与前后端联调_第5张图片

创建 08-计算属性.html

例1:模板中使用js表达式

new Vue({
    el: '#app',
    data: {
        message: 'hello'
    }
})

模板表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会难以维护。

原始值: {{ message }}

反转消息: {{ message.split('').reverse().join('') }}

所以,对于任何复杂逻辑,你都应当使用计算属性

例2:使用计算属性

computed: {
    reversedMessage () {
        console.log('计算属性执行')
        return this.message.split('').reverse().join('')
    }
}

反转消息: {{ reversedMessage }}

例3:使用方法

methods:{
    reversed () {
        console.log('方法执行')
        return this.message.split('').reverse().join('')
    }
}

反转消息: {{ reversed() }}

计算属性缓存 vs 方法
(https://cn.vuejs.org/v2/guide/computed.html#计算属性缓存-vs-方法)

看起来计算属性和方法能完成相同的功能,那么他们有什么区别呢?

  • **计算属性基于缓存:**在相关依赖发生改变时它们才会重新求值。
  • 方法将总会再次执行

反转消息: {{ reversedMessage }}

反转消息: {{ reversedMessage }}

反转消息: {{ reversed() }}

反转消息: {{ reversed() }}

5 关于Vue组件

5.1 什么是组件

组件(Component)是 Vue.js 最强大的功能之一。

组件可以扩展 HTML 元素,封装可重用的代码。

组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用界面都可以抽象为一个组件树:

前端项目开发流程与前后端联调_第6张图片

5.2 前端项目组件分析

5.2.1、三要素

  • 入口js:src/main.js
  • 入口页面:src/App.vue
  • 路由:src/router/index.js

main.js 中引入了App.vue和 router/index.js,根据路由配置,App.vue中会显示相应的页面内容

5.2.2、入口文件

src/main.js

前端项目开发流程与前后端联调_第7张图片

5.2.3、主页面模块

src/App.vue

前端项目开发流程与前后端联调_第8张图片

5.2.4、路由模块

src/router/index.js

前端项目开发流程与前后端联调_第9张图片

5.2.5、登录页面组件

前端项目开发流程与前后端联调_第10张图片

5.3 前端项目布局分析

5.3.1、路由模块

src/router/index.js

前端项目开发流程与前后端联调_第11张图片

5.3.2、布局模块

src/views/layout/Layout.vue

前端项目开发流程与前后端联调_第12张图片

5.3.3、核心内容区域

src/views/layout/components/AppMain.vue

前端项目开发流程与前后端联调_第13张图片

5.3.4、讲师列表页面组件

前端项目开发流程与前后端联调_第14张图片

你可能感兴趣的:(front)