js,后端,css记录
一、后端接口开发常见问题
1. MyBatis 插入数据后返回自增主键
问题:使用 MyBatis 插入数据时,需要获取数据库自动生成的主键(如id
),用于后续关联操作(如插入子表数据)。
解决方案:在 Mapper XML 中配置useGeneratedKeys
和keyProperty
,开启主键自动返回:
xml
<insert id="insertTuwen" useGeneratedKeys="true" keyProperty="id">insert into tuwen (user_name, avatar_url, title) values (#{userName}, #{avatarUrl}, #{title})
</insert>
useGeneratedKeys="true"
:告诉 MyBatis 启用主键自动生成。keyProperty="id"
:将生成的主键赋值给实体类的id
属性。
插入后,通过实体类的getId()
即可获取主键:
java
运行
tuwenMapper.insertTuwen(tuwen); // 插入数据
Long tuwenId = tuwen.getId(); // 直接获取自增主键
2. 跨域问题(CORS policy)
问题:前端(如localhost:5173
)调用后端接口(如localhost:8090
)时,浏览器报跨域错误:
plaintext
Access to XMLHttpRequest at 'http://localhost:8090/...' from origin 'http://localhost:5173' has been blocked by CORS policy
解决方案:后端添加 CORS 配置,允许前端域名访问。以 Spring Boot 为例:
java
运行
@Configuration
public class CorsConfig {@Beanpublic CorsFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();config.addAllowedOrigin("http://localhost:5173"); // 允许前端域名config.setAllowCredentials(true); // 允许携带Cookieconfig.addAllowedMethod("*"); // 允许所有HTTP方法config.addAllowedHeader("*"); // 允许所有请求头UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", config); // 所有接口生效return new CorsFilter(source);}
}
3. 前端传递文件参数格式错误(400 Bad Request)
问题:前端上传图片时,通过 URL 参数或 JSON 传递File
对象,后端报400
错误,提示参数格式错误。
解决方案:使用FormData
传递文件和普通参数(FormData
专为二进制数据设计):
javascript
运行
// 前端代码
const formData = new FormData();
// 添加普通参数
formData.append('userName', 'test');
formData.append('title', '示例标题');
// 添加文件(循环添加多个文件)
images.forEach(img => {formData.append('images', img.file); // 键名与后端@RequestParam一致
});
// 提交请求
axios.post('/tuwen/upTuwen', formData);
后端接收:
java
运行
@PostMapping("/upTuwen")
public void upTuwen(@RequestParam("userName") String userName,@RequestParam("images") List<MultipartFile> images // 接收文件列表
) {// 处理逻辑
}
4. 数据库外键关联映射错误(Unknown column 'tuwen')
问题:实体类Images
关联了Tuwen
对象,但数据库中实际存储外键tuwen_id
,插入时报 “未知列tuwen
” 错误。
解决方案:区分实体类关联对象和数据库外键字段:
java
运行
@Entity
public class Images {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;// 数据库外键字段(映射tuwen_id列)@Column(name = "tuwen_id")private Long tuwenId;// 关联对象(仅用于查询,不参与插入/更新)@ManyToOne@JoinColumn(name = "tuwen_id", insertable = false, updatable = false)private Tuwen tuwen;// getter/setter
}
tuwenId
:映射数据库tuwen_id
列,负责插入外键值。tuwen
:仅用于关联查询,通过insertable=false, updatable=false
避免参与读写。
二、前端 Vue3 组件开发问题
1. 抖音风格点赞弹窗实现
需求:点击点赞按钮或接口请求成功后,显示居中的 “点赞成功” 弹窗,自动消失并带动画。
实现代码:子组件(LikePopup.vue
):
vue
<template><div class="popup" v-if="visible">点赞成功!</div>
</template><script setup>
import { ref } from 'vue';const visible = ref(false);// 显示弹窗方法(暴露给父组件)
const showPopup = () => {visible.value = true;setTimeout(() => visible.value = false, 2000); // 2秒后隐藏
};defineExpose({ showPopup }); // 暴露方法
</script><style scoped>
.popup {position: fixed;top: 0; left: 0; right: 0; bottom: 0;margin: auto;width: 150px;height: 60px;display: flex;align-items: center;justify-content: center;background: rgba(0,0,0,0.8);color: white;border-radius: 8px;animation: fade 2s;
}@keyframes fade {0% { opacity: 0; }20% { opacity: 1; }80% { opacity: 1; }100% { opacity: 0; }
}
</style>
父组件调用:
vue
<template><div><LikePopup ref="likePopup" /><button @click="handleLike">点赞</button></div>
</template><script setup>
import { ref } from 'vue';
import LikePopup from './LikePopup.vue';//生成子组件的实例,方便调用
const likePopup = ref(null);// 点击按钮或接口成功后触发
const handleLike = async () => {await api.like(); // 调用后端接口likePopup.value.showPopup(); // 显示弹窗
};
</script>
在 Vue3 中,通过 ref=""
和 const xxx = ref(null)
配合组件实例的逻辑可以简单理解为:前者是给组件打 “标识”,后者是在代码中 “抓取” 这个标识对应的组件实例,最终通过实例调用组件内部暴露的方法或访问属性。
核心逻辑:
ref="likePopupRef"
:在模板中给子组件添加一个 “标识名”,相当于给组件贴了一个标签,告诉 Vue:“这个组件可以通过likePopupRef
找到”。const likePopupRef = ref(null)
:在脚本中创建一个响应式变量,初始值为null
。Vue 会自动将模板中ref="likePopupRef"
对应的组件实例赋值给这个变量(所以最终likePopupRef.value
就是子组件实例)。likePopupRef.value.showPopup()
:通过实例调用子组件暴露的方法(必须是子组件用defineExpose
公开的方法,否则无法访问)。