一、父组件使用ref模板调用子组件方法的问题
1. 问题表象
父组件使用ref调用子组件的方法时,在dev模式正常运行,无任何报错。在build后生产环境运行时,提示子组件方法找不到。 
2. 场景复现
- 父组件代码
<template>
……
</template>
<script setup>
import Tabbar from "@/components/common/Tabbar.vue";
import LoginPopup from "@/components/common/LoginPopup.vue";
import {computed, onMounted, reactive, ref} from "vue";
// 引入公共方法
let {refLoginPopup} = global()
// 引入系统与设置模块
let {……} = setting(……)
// 公共方法
function global() {
……
// 提示登录组件对象
const refLoginPopup = ref(null)
……
return {
refLoginPopup
}
}
function setting(……) {
……
return {……}
}
</script>
<style scoped lang="scss">
……
</style>
- 子组件代码
<template>
<van-popup v-model:show="popupIsShow">
<section>
<div class="tip-img">
<img :src="'/src/assets/images/login-popup.png'" alt=""/>
</div>
<div class="tip-content">
<h3>您还没有登录</h3>
<p>请先登录或注册再进行此操作</p>
</div>
<div class="tip-btn">
<van-button color="linear-gradient(to right, #ffb061, #ff795d)" round
@click="toLogin">立即登录
</van-button>
<p @click="toRegister">还未注册?</p>
</div>
</section>
</van-popup>
</template>
<script setup>
import {Popup, Button} from 'vant';
import {ref} from "vue";
import {useRouter} from "vue-router";
const router = useRouter()
// 默认不显示登录提示弹窗
const popupIsShow = ref(false);
// 显示登录提示弹窗
const showPopup = () => {
popupIsShow.value = true;
};
……
defineExpose({
showPopup, popupIsShow
})
</script>
<style lang="scss" scoped>
……
</style>
3. 问题分析
由于该页面功能模块较多,为便于开发,按功能模块拆分到了不同的函数中,但定义ref模板时,也将其放在单独的函数中,导致vite打包时不能识别正常打包。
4. 解决办法
父组件定义ref模板时,一定要放在<script setup>标签内,不要通过function定义函数然后return返回的方式定义。
# 父组件
<template>
……
</template>
<script setup>
import Tabbar from "@/components/common/Tabbar.vue";
import LoginPopup from "@/components/common/LoginPopup.vue";
import {computed, onMounted, reactive, ref} from "vue";
// 提示登录组件对象
const refLoginPopup = ref(null)
// 引入公共方法
let {……} = global()
// 引入系统与设置模块
let {……} = setting(……)
// 公共方法
function global() {
……
return {
……
}
}
function setting(……) {
……
return {……}
}
</script>
<style scoped lang="scss">
……
</style>
二、子组件使用父组件传参时双向绑定的问题
1. 问题表象
子组件接收并使用父组件参数时,在dev模式正常运行,无任何报错。在build后生产环境运行时,提示子组件方法找不到。 
2. 场景复现
- 父组件
<template>
<div v-title="title">
……
<Tabbar :activeBar="0"></Tabbar>
</div>
</template>
<script setup>
import Tabbar from '@/components/common/Tabbar.vue'
import {onMounted, reactive, ref} from "vue";
……
</script>
<style lang="scss">
……
</style>
- 子组件
<template>
<van-tabbar v-model="props.activeBar" placeholder safe-area-inset-bottom>
……
</van-tabbar>
</template>
<script setup>
import {ref} from 'vue';
const props = defineProps({
// 当前激活的导航栏id
activeBar: {
type: Number,
required: false,
default: 0
}
})
</script>
<style lang="scss" scoped>
</style>
3. 问题分析
父组件向子组件传值时,通常不需要做双向绑定,因为是只读属性,如果需要更改值,子组件使用emit向父组件传递事件。但由于项目中使用vant,当前激活的item必须使用双向绑定。参考文档https://vant-contrib.gitee.io/vant/v3/#/zh-CN/tabbar。因此会出现上述问题
4. 解决办法
子组件模板中使用父组件参数双向绑定时(实际开发过程中不推荐这样做,但vant的tabbar组件只能双向绑定)。要使用props.XXX
# 子组件
<template>
<van-tabbar v-model="props.activeBar" placeholder safe-area-inset-bottom>
…………
</van-tabbar>
</template>
<script setup>
import {ref} from 'vue';
const props = defineProps({
// 当前激活的导航栏id
activeBar: {
type: Number,
required: false,
default: 0
}
})
const active = ref(0)
</script>
<style lang="scss" scoped>
</style>
三、vite项目引用本地图片的问题
1. 问题表象
template和script setup使用本地图片资源时,使用文件路径,dev模式正常,build后找不到资源文件。 
2. 问题分析
详细原因可参考官方vite文档https://cn.vitejs.dev/guide/assets.html,主要原因是vite打包时,src属性解析成字符串,而不是路径,类似动态地址,所以无法被解析打包。
3. 解决办法
- template使用图片资源时,直接采用标签来引入图片
<template>
<div class="tip-img">
<img src="/src/assets/images/login-popup.png" alt=""/>
</div>
</template>
- script setup使用图片资源时,利用import获取打包文件的动态地址
<script setup>
import QzoneImg from '@/assets/images/qq-zone.png'
const options = [
[
{name: 'QQ空间', icon: QzoneImg},
{name: '微博', icon: 'weibo'},
{name: 'QQ', icon: 'qq'},
{name: '微信', icon: 'wechat'},
{name: '朋友圈', icon: 'wechat-moments'},
],
[
{name: '复制链接', icon: 'link'},
{name: '二维码', icon: 'qrcode'}
],
]
</script>
- 或者也可以在script setup中import引入,赋值给变量名,然后在template中使用变量名。