defineComponent 的作用
defineComponent 主要用于 TypeScript 的类型推导。
如果直接使用 export default {},TypeScript 可能会将 {} 视为普通对象。而使用 export default defineComponent({}),则可以正确地推导组件选项的类型。通俗来说,在 TypeScript 环境下开发 Vue 组件,使用 defineComponent 是最佳实践。
Vue 3 使用 Element Plus
安装与配置按需引入
首先安装 Element Plus 和自动导入插件:
npm install element-plus
npm install -D unplugin-vue-components然后修改 vue.config.js(Vue CLI 项目):
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = {
// 注意:修改 webpack 配置需要放在 configureWebpack 中
configureWebpack: {
plugins: [
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
}常见报错: Invalid options in vue.config.js: "plugins" is not allowed原因:plugins 属性不能直接放在 vue.config.js 根对象下,必须包裹在 configureWebpack 中。
配置完成后,项目中即可直接使用 Element Plus 组件,无需在 main.js 中再次导入。
配置 HTML 标题
如果需要动态修改 index.html 中的标题(使用 htmlWebpackPlugin.options.title),可以在 vue.config.js 中使用 chainWebpack 进行修改:
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].title = '你的自定义标题'
return args
})
}
}Style Scoped
在 <style> 标签上添加 scoped 属性,可以确保样式只作用于当前组件,实现样式隔离。
<style scoped>
/* 仅当前组件生效 */
</style>Vue 3 添加全局方法
在 Vue 3 中,不再使用 Vue.prototype 挂载全局方法,而是通过 app.config.globalProperties。
挂载(main.js):
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import { ElMessage } from 'element-plus'
const app = createApp(App)
// 挂载全局方法
app.config.globalProperties.$http = axios
app.config.globalProperties.$message = ElMessage
app.mount('#app')使用(组件内 setup):
import { getCurrentInstance } from 'vue'
export default {
setup() {
const { proxy } = getCurrentInstance()
// 调用全局方法
proxy.$http.get(...)
proxy.$message.success(...)
}
}Vue 3 表单验证
Vue 3 中获取 ref 实例的方式发生了变化,不再使用 this.$refs。
import { getCurrentInstance } from 'vue'
export default {
setup() {
const { proxy } = getCurrentInstance()
const submitForm = () => {
// 这里的 proxy 相当于 Vue 2 中的 this
proxy.$refs.formRef.validate((valid) => {
console.log(valid)
})
}
return { submitForm }
}
}Axios POST 请求数据格式问题
Axios 默认发送的数据格式是 JSON (application/json)。如果后端需要 application/x-www-form-urlencoded 格式,会导致参数接收失败。
解决方案:使用 qs 模块在请求拦截器中序列化数据。
import axios from 'axios'
import qs from 'qs'
// 请求拦截器
axios.interceptors.request.use(config => {
// 将 data 转换为查询字符串格式
if (config.method === 'post') {
config.data = qs.stringify(config.data)
}
return config
})Vue Router 路由传参
在 Vue 3 中,useRouter 和 useRoute 是两个不同的 Hook:
useRouter():返回 router 实例,用于执行路由跳转(相当于this.$router)。useRoute():返回当前路由对象,用于获取参数(相当于this.$route)。
路由跳转(传参):
import { useRouter } from "vue-router";
const router = useRouter();
router.push({
path: '/pc/articleList',
// 使用 query 传参
query: {
cate_id_son: data.cate_id_son
}
});接收参数:
import { useRoute } from "vue-router";
const route = useRoute();
console.log(route.query); // 获取参数Vue 3 watchEffect
watchEffect 类似于 React 的 useEffect。它会立即执行传入的函数,并响应式追踪其依赖,并在依赖变更时重新运行该函数。
import { watchEffect } from 'vue'
watchEffect(async () => {
// 页面加载时会立即执行一次
// 当 route.query.sname 发生变化时,也会触发重新执行
const { data: { data: res } } = await proxy.$http.get('/user/subjectfiles?sname=' + route.query.sname)
data.Listdata = res
})