一、项目说明
校园旧物回收商城,使用Springboot+Vue2.x开发,使用了JWT、MybatisPlus、JWT、ElementUI
项目已经开源在https://github.com/astudent2020/Campus_waste_recycling
文章目录
- 一、项目说明
- 一、说明书
- 1、用户主页:
- 2、登录注册页面
- 3、后台页面
- 4、Token测试点
- 二、页面展示
- 1、首页
- 2、旧物上传
- 3、购物车
- 4、个人中心
- 5、订单管理
- 6、登录
- 7、注册
- 8、后台首页
- 9、个人中心
- 10、用户管理
- 11、类别管理
- 12、商品管理
- 13、订单管理
- 二、主页说明
- 一、说明
- 1、修改之前的前端结构,使用utils完成统一接口
- 2、更新front和back中的header、aside
- 1、FrontTemplate.vue表示前端模板【Header、Aside】
- 2、BackTemplateb.vue表示后端模板【Header、Aside】
- 二、主页前端
- 1、header
- header头像
- 2、Aside
- 3、主页详情内容展示
- 1、创建数据库
- 三、主页的条件查询
- 四、主页的详情展示
- 五、购物车的处理
- 六、购物车结算
- 七、订单展示
- 八、注册页面
- 九、旧物上传
- 十、权限设置
- 三、后台说明
- 四、bug记录日志
- 1、使用utils设置config.js导致Token未能正常放入请求头
- 2、路由守卫失效
- 五、创新性实验
- Vue中方法重写
一、说明书
1、用户主页:
主页:http://localhost:8080/ 用户只需要使用
http://localhost:8080/ 即可访问主页 主页的真实路径是
http://localhost:8080/index/body
2、登录注册页面
登录:http://localhost:8080/user/login
提供管理员登录和用户登录
用户名:daetz
密码:123456
登陆成功后会返回主页,并给出相关的提示,提示登录成功
注册:http://localhost:8080/user/register
注册需要用户输入个人信息,大部分都是使用小组件完成
3、后台页面
后台主页:http://localhost:8080/admin
用户只需要使用
http://localhost:8080/admin 即可访问管理员后台
管路员主页的真实路径是 http://localhost:8080/admin/pageone
4、Token测试点
用户可以使用 http://localhost:8080/admin/pagetwo
来检测数据前端后端数据是否互通,以及Token是否能正常被放入请求头中。
二、页面展示
1、首页
2、旧物上传
3、购物车
4、个人中心
信息修改
5、订单管理
6、登录
7、注册
8、后台首页
9、个人中心
10、用户管理
11、类别管理
12、商品管理
13、订单管理
二、主页说明
一、说明
1、修改之前的前端结构,使用utils完成统一接口
2、更新front和back中的header、aside
描述:
1、FrontTemplate.vue表示前端模板【Header、Aside】
- Header
访问路径
/index
/shoppingcart
/back
/login
/register
- Aside
访问路径
/front/digital
/front/food
/font/book
2、BackTemplateb.vue表示后端模板【Header、Aside】
Aside数据包括
二、主页前端
1、header
设置访问路径
header头像
<el-menu-item index="9">
<el-dropdown style="width: 150px; cursor: pointer; text-align: right">
<div style="display: inline-block">
<img :src="userImage" alt=""
style="width: 40px; border-radius: 50%; position: relative; right: 5px">
<span style="color: white">{{username}}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
</div>
<el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center">
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<router-link to="/back" style="text-decoration: none">后台管理</router-link>
</el-dropdown-item>
<el-dropdown-item style="font-size: 12px; padding: 5px 0">
<span style="text-decoration: none" @click="logout">退出</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-menu-item>
2、Aside
访问路径
/front/digital
/front/food
/font/book
3、主页详情内容展示
前台给出的数据
1、创建数据库
- id
- name
- price
- imgUrl
- description
- sale
- store
增加部分数据
三、主页的条件查询
前端代码
<template>
<div>
<el-row>
<el-col :span="8" v-for="item in goods" :key="item.id">
<el-card shadow="hover" style="margin:20px 0;">
<div style="text-align: center;">
<img :src="item.imageUrl" style="height: 150px; width: 150px;">
</div>
<div style="padding: 14px;">
<span style="font-size: 14px;font-weight: bold">{{item.name}}</span>
<div style="margin-top:12px;">
<span style="font-size: 18px;color: #f60;">¥{{item.price}}</span>
</div>
<div style="text-align:right;margin-top:12px;">
<router-link :to="'/index/detail?'+item.id">
<el-button type="primary" size="small">查看详情</el-button>
</router-link>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-pagination
background
layout="prev, pager, next"
:page-size=3
:total="total"
@current-change="page">
</el-pagination>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: 'book1',
data () {
return {
total:null,
goods:null,
}
},
methods: {
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/goods/findByCategory/'+currentPage+'/3/1').then(function (resp){
_this.goods=resp.data.data.records
_this.total=resp.data.data.total
})
},
},
created() { //alert 初始化操作
const _this=this
request.get('/goods/findByCategory/1/3/1').then(function (resp){
console.log(resp.data)
_this.goods=resp.data.data.records
_this.total=resp.data.data.total
_this.size=resp.data.data.size
})
},
}
</script>
<style scoped>
</style>
后端代码
package com.example.cshand.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.cshand.DTO.ResultDataDTO;
import com.example.cshand.entity.Goods;
import com.example.cshand.mapper.GoodsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author daetz
* @creat 2023/6/8
**/
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private GoodsMapper goodsMapper;
@RequestMapping("/findByCategory/{PageNum}/{size}/{categoryId}")
public ResultDataDTO findGoods(
@PathVariable("PageNum") Integer PageNum,
@PathVariable("size") Integer size,
@PathVariable("categoryId") Integer categoryId
){
Page<Goods> page = new Page<>(PageNum, size);
// 创建查询条件对象
QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("category_id", categoryId); // 根据categoryId进行条件查询
Page<Goods> result = goodsMapper.selectPage(page, queryWrapper);
return ResultDataDTO.success(result);
}
}
四、主页的详情展示
前端
<template>
<div>
<div style="margin-top: 20px; margin-left: 20px; font-size: 24px;">
商品详情
</div>
<el-row style="margin-top: 20px;">
<el-col :span="8">
<img :src="goods.imageUrl" style="height: 350px; width: 350px; margin: 20px;">
</el-col>
<el-col :span="12" style="padding: 20px 20px 20px 40px;">
<div style="margin-bottom: 20px; font-size: 28px; font-weight: bold;">{{ goods.name }}</div>
<div style="font-size: 20px; color: #f60;">¥{{ goods.price }}</div>
<div style="margin-top: 24px;">商品详情:{{ goods.description }}</div>
<div style="margin-top: 24px;">销量:{{ goods.sale }}</div>
<div style="margin-top: 24px;">库存:{{ goods.store }}</div>
<div style="position: absolute; bottom: 20px; right: 40px;">
<el-button type="success" @click="buy">加入购物车</el-button>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: 'ShoppingDetail',
data() {
return {
goods: null,
}
},
methods: {
buy() {
const cart={
id:this.goods.id,
goods_id:this.goods.goods_id,
image_url:this.goods.image_url,
count:1,
price:this.goods.price,
};
request.post("/cart/saveOrUpdate", cart)
.then(resp => {
if (resp.data.code === "200") {
this.$message.success("加入购物车成功");
} else {
this.$message.error("加入购物车失败");
}
});
},
},
created() {
const _this = this;
request.get(`/goods/findById/${this.$route.query.id}`).then(function(resp) {
console.log(resp.data);
_this.goods = resp.data.data;
console.log(_this.goods);
});
const storedUser = localStorage.getItem('user');
const user = JSON.parse(storedUser);
this.username=user.username
},
}
</script>
<style scoped>
</style>
加入后端
package com.example.cshand.controller;
import com.example.cshand.DTO.ResultDataDTO;
import com.example.cshand.entity.Cart;
import com.example.cshand.service.impl.CartServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* @author daetz
* @creat 2023/6/8
**/
@RestController
@RequestMapping("/cart")
public class CartController {
@Autowired
private CartServiceImpl cartService;
/**
* 加入购物车
* @param cart
* @return
*/
@PostMapping("/saveOrUpdate")
public ResultDataDTO SaveCart(@RequestBody Cart cart){
boolean save = cartService.saveOrUpdate(cart);
return ResultDataDTO.success(save);
}
}
五、购物车的处理
request.post("/cart/saveOrUpdate", cart)
.then(resp => {
if (resp.data.code === "200") {
this.$message.success("加入购物车成功");
} else {
this.$message.error("加入购物车失败");
}
});
},
},
六、购物车结算
结算事件
}
@RequestMapping("/deleteById/{id}")
public ResultDataDTO deleteById(@PathVariable Integer id){
boolean result = cartService.removeById(id);
return ResultDataDTO.success(result);
}
}
// 将订单数据发送到服务器
request.post("/order/create", order)
.then(resp => {
if (resp.data.code === "200") {
this.$message.success("订单创建成功");
request.post("/cart/deleteById/"+order.goodsId)
.then(resp => {
if (resp.data.code === "200"){
this.$message.info("购物车清除成功");
}else{
this.$message.error("购物车清除失败");
}
});
} else {
this.$message.error("订单创建失败");
}
});
}
七、订单展示
<template>
<div>
<el-table :data="orders" style="width: 100%">
<el-table-column prop="id" label="订单ID"></el-table-column>
<el-table-column prop="username" label="用户姓名"></el-table-column>
<el-table-column prop="goodsName" label="商品名称"></el-table-column>
<el-table-column prop="count" label="数量"></el-table-column>
<el-table-column prop="price" label="单价"></el-table-column>
<el-table-column prop="subtotal" label="小计"></el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size="10"
:total="total"
@current-change="page">
</el-pagination>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name:'OrderShow',
data() {
return {
total:null,
goods:null,
orders: [] // 存储订单数据
};
},
methods: {
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/order/findAll/'+currentPage+'/10').then(function (resp){
_this.orders=resp.data.data.records
_this.total=resp.data.data.total
})
},
},
created() { //alert 初始化操作
const _this=this
request.get('/order/findAll/1/10').then(function (resp){
console.log(resp.data)
_this.orders=resp.data.data.records
_this.total=resp.data.data.total
_this.size=resp.data.data.size
})
},
}
</script>
<template>
<div>
<el-table :data="orders" style="width: 100%">
<el-table-column prop="id" label="订单ID"></el-table-column>
<el-table-column prop="username" label="用户姓名"></el-table-column>
<el-table-column prop="goodsName" label="商品名称"></el-table-column>
<el-table-column prop="count" label="数量"></el-table-column>
<el-table-column prop="price" label="单价"></el-table-column>
<el-table-column prop="subtotal" label="小计"></el-table-column>
</el-table>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name:'OrderShow',
data() {
return {
orders: [] // 存储订单数据
};
},
mounted() {
// 在组件加载完成后获取订单数据
this.fetchOrders();
},
methods: {
fetchOrders() {
// 发起请求获取订单数据
request.get('/order/findAll')
.then(response => {
console.log(response);
console.log(response.data.data)
// 请求成功,将订单数据赋值给 orders 数组
this.orders = response.data.data;
})
.catch(error => {
// 处理错误
console.error(error);
});
}
}
}
</script>
分页查询
@RequestMapping("/findAll/{PageNum}/{size}")
public ResultDataDTO findAll(@PathVariable("PageNum") Integer PageNum, @PathVariable("size") Integer size){
Page<Orders> page = new Page<>(PageNum, size);
Page<Orders> result = ordersMapper.selectPage(page, null);
return ResultDataDTO.success(result);
}
}
八、注册页面
修复用户头像无法正常显示
methods: {
handleSelect(key, keyPath) {
console.log(key, keyPath);
},
logout() {
// 调用 Vue Router 的 push 方法,将路径跳转到 '/login'
router.push('/index/login')
// 删除本地存储的用户信息
localStorage.removeItem('user')
// 显示退出成功的消息
this.$message.success('退出成功')
}
},
created() {
const storedUser = localStorage.getItem('user');
const user = JSON.parse(storedUser);
this.username=user.username
this.userImage=user.avatar
},
}
九、旧物上传
增加数据库
十、权限设置
路由守卫
import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from "@/views/front/Index.vue";
import adminHome from "@/views/back/adminHome.vue";
import UserLogin from "@/views/front/UserLogin.vue";//用户登录页面
import Register from "@/views/front/UserRegister.vue";
import AddUserInformation from "@/views/back/AddUserInformation.vue";
import UserUpdate from "@/views/back/UserUpdate.vue";
import AdminLogin from "@/views/back/AdminLogin.vue";
//后台
import PageTwo from "@/views/back/PageTwo.vue";
import PageThree from "@/views/back/PageThree.vue";
import PageFour from "@/views/back/PageFour.vue";
import PageFive from "@/views/back/PageFive.vue";
import GoodsUpdate from "@/views/back/GoodsUpdate.vue";
/**
* 主页
*/
//主页设计和详情展示
import ShoppingHome from "@/views/front/ShoppingHome.vue";
import ShoppingDetail from "@/views/front/ShoppingDetail.vue";
import UserInformation from "@/views/front/UserInformation.vue";
import ChangeInformation from "@/views/front/ChangeInformation.vue";
//后端信息
import AdminInformation from "@/views/back/AdminInformation.vue";
import AdminChangeInformation from "@/views/back/AdminChangeInformation.vue";
//aside
import digital1 from "@/views/Aside/digital1.vue"
import digital2 from "@/views/Aside/digital2.vue"
import digital3 from "@/views/Aside/digital3.vue"
import book1 from "@/views/Aside/book1.vue";
import book2 from "@/views/Aside/book2.vue";
import book3 from "@/views/Aside/book3.vue";
import food1 from "@/views/Aside/food1.vue";
import food2 from "@/views/Aside/food2.vue";
import food3 from "@/views/Aside/food3.vue";
import CartShow from "@/views/front/CartShow.vue";
import OrderShow from "@/views/front/OrderShow.vue";
import GoodsUpload from "@/views/front/GoodsUpload.vue";
Vue.use(VueRouter)
const routes = [
{
path: '/',
redirect:'/index/home',
},
{
path: '/index',
name: '起始页',
component: Index,
children:[
{
path:'home',
name:'商品购物主页',
component: ShoppingHome,
},
{
meta: {
requiresAuth: true // 设置需要登录才能访问
},
name: '更新个人信息',
component: ChangeInformation,
path: 'change'
},
{
meta: {
requiresAuth: true // 设置需要登录才能访问
},
name:'个人信息',
path: 'information',
component: UserInformation,
},
{
name:'商品详情展示',
component: ShoppingDetail,
path:'detail',
},
{
path: 'login',
name:'用户登录页面',
component: UserLogin
},
{
path: 'register',
name:'用户注册页面',
component: Register
},
{
meta: {
requiresAuth: true // 设置需要登录才能访问
},
name:'购物车结算',
component: CartShow,
path:'cart',
},
{
meta: {
requiresAuth: true // 设置需要登录才能访问
}, name:'旧物上传',
component: GoodsUpload,
path: 'upload'
},
{
meta: {
requiresAuth: true // 设置需要登录才能访问
},
name:'订单中心',
component: OrderShow,
path: 'order'
},
{
path:'digital1',
name:'电脑',
component: digital1,
},
{
path:'digital2',
name:'手机',
component: digital2,
},
{
path:'digital3',
name:'平板',
component: digital3,
},
{
path:'food1',
name:'面包',
component: food1,
},
{
path:'food2',
name:'牛奶',
component: food2,
},
{
path:'food3',
name:'饮料',
component: food3,
},
{
path:'book1',
name:'教材',
component: book1,
},
{
path:'book2',
name:'人文',
component: book2,
},
{
path:'book3',
name:'艺术',
component: book3,
},
]
},
{
path: '/admin',
name: '管理员主页',
component: adminHome,
meta: {
requiresAuth: true // 设置需要登录才能访问
},
children:[
{
path: 'information',
name: '后台用户信息展示',
component: AdminInformation,
},
{
path: 'changeinfo',
name: '后台更新用户信息',
component: AdminChangeInformation,
},
{
path:'pagetwo',
name:'用户',
component: PageTwo,
},
{
path:'pagethree',
name:'商品1',
component: PageThree,
},
{
path:'pagefour',
name:'商品2',
component: PageFour,
},
{
path:'pagefive',
name:'商品3',
component: PageFive,
},
{
path: 'addUser',
name:'用户信息添加',
component: AddUserInformation,
meta: {
requiresAuth: true // 设置需要登录才能访问
}
},
{
path: 'update',
name:'用户更新',
component: UserUpdate,
meta: {
requiresAuth: true // 设置需要登录才能访问
},
},
{
name:'修改商品状态',
path: 'change',
component: GoodsUpdate,
}
]
},
{
path: '/adminLogin',
name:'后台管理员登录',
component: AdminLogin
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
// 路由守卫
router.beforeEach((to, from, next) => {
// 判断当前路由是否需要登录才能访问
if (to.matched.some(record => record.meta.requiresAuth)) {
// 判断用户是否已经登录
if (!localStorage.getItem('user')) {
// 如果没有登录,给出提示
Vue.prototype.$message.error('您还未登录,请先登录!')
// 等待2秒后跳转
setTimeout(() => {
next('/index/home')
}, 2000)
return // 终止路由导航
}
}
// 其他情况继续跳转
next()
})
export default router
v-if自动渲染
注意这里面不能使用 role===1来判断
如果你通过 JSON 解析或从服务器获取的数据中,role
的值是字符串类型的 '1'
,那么在比较时确实需要将条件判断中的值也使用字符串形式来进行比较,如 role === '1'
。
在进行 JSON 解析时,属性值的类型会被转换为相应的 JavaScript 数据类型。如果 role
在 JSON 数据中被定义为字符串类型的 '1'
,那么在解析后,role
将保持为字符串类型。这就解释了为什么在比较时需要使用字符串形式的 '1'
。
确保在解析 JSON 数据后,检查 role
的类型,并根据需要进行类型转换或使用适当的条件判断进行比较。
三、后台说明
点击开关调整商品状态
忘记增加数据持久化
<div class="demo-input-suffix">
<el-input
placeholder="按照日期查找"
suffix-icon="el-icon-date"
v-model="input1"
style="width: 150px;float: left;margin:5px" >
</el-input>
<el-input
placeholder="按照姓名查找"
prefix-icon="el-icon-search"
v-model="input2"
style="width: 150px;float: left;margin:5px">
</el-input>
<el-button style="width: 70px;float: left;margin:5px" @click="search">查询</el-button>
<el-button style="width: 70px;float: left;margin:5px" @click="resetForm">重置</el-button>
<el-button style="width: 70px;float: left;margin:5px" @click="addUser" type="primary" plain>新增</el-button>
<el-button style="width: 140px;float: left;margin:5px" type="danger" plain>批量删除</el-button>
</div>
search(){
const _this = this;
request.get('/admin/findByName/'+_this.input2).then(function(resp) {
console.log(resp)
_this.tableData=resp.data
_this.total=resp.data.length
});
},
addUser(){
this.$router.push('/addUser')
},
resetForm(){
this.input1='';
this.input2='';
},
deleteUser(row){
const _this=this
request.delete('/admin/delete/'+row.id).then(function (resp){
//console.log(resp)
alert("删除成功")
window.location.reload();
})
},
edit(row) {
this.$router.push({
path:'/update',
query:{
id:row.id
}
})
//row.id<点击的id>
},
信息卡片
四、bug记录日志
1、使用utils设置config.js导致Token未能正常放入请求头
检测发现是命名未统一,包含user
和username
仍然出错,忘记修改成request了
确保你在发送请求时使用了request
对象来发起请求,而不是直接使用axios
请确保你使用了request
对象发送请求,并且在发送请求时会自动应用拦截器中设置的请求头。如果你直接使用axios
对象发送请求,那么拦截器中设置的请求头将不会生效。
2、路由守卫失效
- 忘记导入Vue
在代码中,导入Vue
是为了使用Vue.prototype.$message.error
,该语句用于在路由守卫中显示错误消息。
Vue.prototype.$message.error
是使用Vue的原型属性$message
来显示错误消息的方法。通过导入Vue
,你可以在路由守卫中访问Vue实例,并使用$message.error
方法来显示错误消息。
请注意,确保你的项目中已经安装并正确导入了Vue库。如果你的项目中没有使用Vue,或者没有安装Vue相关依赖,那么你可能不需要导入Vue
。但在代码中使用了Vue.prototype.$message.error
的情况下,需要确保Vue正确导入和配置。
import request from '@/utils/request'; // 导入自定义的request对象
export default {
name: "PageTwo",
methods:{
search() {
const _this = this;
request.get('/admin/findByName/' + _this.input2).then(function(resp) {
console.log(resp);
_this.tableData = resp.data;
_this.total = resp.data.length;
});
},
addUser(){
this.$router.push('/addUser')
},
resetForm(){
this.input1='';
this.input2='';
},
deleteUser(row){
const _this=this
request.post('/admin/delete/'+row.id).then(function (resp){
//console.log(resp)
alert("删除成功")
window.location.reload();
})
},
edit(row) {
this.$router.push({
path:'/update',
query:{
id:row.id
}
})
//row.id<点击的id>
},
page(currentPage){ //alert("wait...") 动态分页
const _this=this
request.get('/findUser/'+currentPage+'/3').then(function (resp){
_this.tableData=resp.data.records
_this.total=resp.data.total
})
}
},
created() {
const _this = this;
request.get('/findUser/1/3').then(function(resp) {
_this.tableData = resp.data.records;
_this.total = resp.data.total;
_this.size = resp.data.size;
console.log(resp.data);
});
},
data() {
return {
input1: '',
input2: '',
total:null,
tableData:null,
avatar:''
}
}
}
五、创新性实验
Vue中方法重写
如果在<view>
标签中嵌套了另一个<view>
标签,并且您想在内部的嵌套视图中使用created
函数进行分页查询,您可以按照以下步骤进行操作。
在Vue组件中,可以通过在嵌套的<view>
组件中定义created
生命周期钩子来执行分页查询逻辑。
<template>
<div>
<!-- 外部view -->
<view>
<view>
<!-- 内部view -->
<!-- 其他代码 -->
</view>
</view>
</div>
</template>
<script>
export default {
components: {
view: {
created() {
// 在内部view的created生命周期钩子中执行分页查询逻辑
this.createdPagination();
},
methods: {
createdPagination() {
// 在这里编写使用created进行分页查询的代码逻辑
// 可以调用API或执行其他必要的操作
}
}
}
在Vue组件中,您可以在外部的<div>
标签中定义一个方法,并在内部的嵌套视图中进行重写。这可以通过使用Vue的组件通信机制来实现。
在外部组件中,定义一个方法,并将其传递给内部视图组件作为属性。然后,内部视图组件可以通过监听属性的变化或使用自定义事件来触发重写的方法。
以下是一个示例代码:
html
<template>
<div>
<!-- 外部view -->
<view :override-method="outerMethod">
<!-- 内部view -->
<!-- 其他代码 -->
</view>
</div>
</template>
<script>
export default {
methods: {
outerMethod() {
// 在外部定义的方法
console.log('Outer method');
}
},
components: {
view: {
props: ['overrideMethod'],
created() {
// 在内部view的created生命周期钩子中执行重写的方法
this.overrideMethod();
},
methods: {
overrideMethod() {
// 在内部重写的方法
console.log('Override method');
}
}
}
}
};
</script>
在上述示例中,我们在外部组件中定义了一个名为outerMethod
的方法。然后,我们通过将该方法作为属性传递给内部视图组件<view>
,并使用:override-method="outerMethod"
绑定。
在内部视图组件中,我们通过props
接收外部传递的方法,并在created
生命周期钩子中调用this.overrideMethod()
来执行重写的方法。内部视图组件中的overrideMethod
方法将覆盖外部视图组件中的同名方法。
当外部视图组件的方法被重写时,内部视图组件可以选择是否调用原始方法,或者完全替代原始方法的逻辑。
请根据您的具体需求调整示例代码,并在内部视图组件中实现适当的重写逻辑。