hesi726
hesi726
  • 发布:2019-08-21 18:37
  • 更新:2020-03-18 11:29
  • 阅读:3308

解决 HBuilderX + UniApp + Ts + 父组件Prop 在微信小程序中 无法绑定的 BUG;

分类:uni-app

项目转到 TS 以后,基本就没有使用过 Js 了。。所以下面的所有代码都使用 TS 作为说明; (PS.,我的项目的 ts 和 vue 是分开的)。

父组件 BaseUniComponent.ts 就是定义了一个 父组件中的 prop
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
export default class BaseUniComponent extends Vue{
@Prop({ default: null})
propInParent: null | string;
}
子组件 UserMoneyDetail.ts (继承子父组件,并且定义了一个子组件内的 prop)
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
import BaseUniComponent from './Basic/BaseUniComponent';
@Component({})
export default class UserIncome extends BaseUniComponent {
@Prop({default: null})
propInComponent: null | string;
}
子组件页面: UserMoneyDetail.vue ( 显示传入进来的 prop 的值)
<template>
<view class="content">
<view>propInComponent: {{propInComponent}}</view>
<view>propInParent: {{propInParent}}</view>
</view>
</template>
<script lang="ts" src='./UserMoneyDetail.ts'></script>
入口页面 unientry.ts
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
import UserMoney from './UserMoneyDetail.vue';
@Component({
components: {
UserMoney
}
})
export default class index extends Vue {
title: string = 'Hello';
}
入口页面 unientry.vue (分别绑定了定义在子组件内部的 prop 和 子组件继承自父类的 prop)
<template>
<view>
<UserMoney :propInComponent='title' :propInParent='title'></UserMoney>
</view>
</template>
<script lang="ts" src='./unientry.ts'></script>

在 h5 中这个毫无疑问正常,会显示 2个 Hello,
但是,编译到微信小程序中,却只会显示一个 Hello; ( 我的版本 , HBuilder X 2.2.2.20190816, )

最终发现一个是 HBuilder x 将代码编译成 微信小程序的问题, 也就是 uni-mp-weixin/dist/index.js 编译时,会丢失从父类继承过来的 prop 的定义;
此文件中第 682行定义了如下函数:
function initVueComponent (Vue, vueOptions) {
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions;
vueOptions = VueComponent.extendOptions;
} else {
VueComponent = Vue.extend(vueOptions);
}
return [VueComponent, vueOptions]
}
根据 vue.d.ts , 我没有找到 extendOptions 的任何说明,估计是一个未公开的属性吧;
但是 VueComponent.extendOptions 这个属性里面不包含有继承自父类的 Prop,这也就使得,后面在根据返回的 vueOptions 去创建 Vue 的实例时,也丢失了从父类继承而来的 Prop, 进而使得在 unientry.vue 中 :propInParent='title' 无法绑定子组件继承子父组件的 Prop;

问题找到,改正倒是非常简单。 修改 initVueComponent 的函数定义就可以了;
function initVueComponent (Vue, vueOptions) {
let inputVueOptions = vueOptions; //方便调试
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions;
vueOptions = VueComponent.extendOptions;

    //#region 往 vueOptions 中补充定义在父组件中但未定义在子组件中的 prop  
let defaultInputVueOptions = inputVueOptions['default'];  
if (defaultInputVueOptions && defaultInputVueOptions.options && defaultInputVueOptions.options.props) {  
    if (!vueOptions.props) vueOptions.props = {};  
    let propsInDefaultInputVueOptions = defaultInputVueOptions.options.props;  
    for (var oneProp in propsInDefaultInputVueOptions) {  
        if (!vueOptions.props[oneProp]) {  
            vueOptions.props[oneProp] = propsInDefaultInputVueOptions[oneProp];  
        }  
    }  
}  
    //#endregion  

} else {
VueComponent = Vue.extend(vueOptions);
}
return [VueComponent, vueOptions]
}
编译到微信小程序中,显示正常( 我的版本 , HBuilder X 2.2.2.20190816, )

顺带做了一个项目模板: https://github.com/hesi726/HBuildX-UniApp-Ts-Template

0 关注 分享

要回复文章请先登录注册

DCloud_UNI_FXY

DCloud_UNI_FXY

https://github.com/dcloudio/uni-app/pull/1383这个是你提的吗?是的话,可以直接修改下,我们来合并
2020-03-18 11:29
m***@qq.com

m***@qq.com

尝试了修改,但是没有起效果呢?
2020-03-17 17:01
老糊涂

老糊涂

不知道这里用extendOptions而不用options的原因是什么,有谁知道吗?
2020-03-07 15:22
2***@qq.com

2***@qq.com

遇到同样的问题。。
请问是要修改huilder的文件吗,还是项目文件, 没找到你说的路径
2019-10-18 16:16