在 Vue 组件实例上更新 props 的正确方法是什么



我正在尝试找出更新在组件实例上创建的propsData的最佳方法。 基本上我有一个签名包装器页面,并收到一堆使用v-html呈现的 html。 然后,我将在该呈现的 html 中创建可变数量的签名板组件。 由于我不知道 html 会是什么,所以我被迫(我能说的最好的(在挂载后即时创建组件。

所以我在父mounted()上运行以下内容:

initializeSignaturePads() {
const signatureAreas = document.querySelectorAll('.signature_area');
// dynamically create a new vue instance for each signature pad and mount onto the respective .signature_area element
// since the html is loaded via ajax, we don't know where to render this template on load, so a new Vue must be created
signatureAreas.forEach(element => {
const id = element.id;
const signatureType = element.classList.contains('initials') ? 'initials' : 'signature';
if (this.needsCustomerSignature(id)) {
let length = this.signatures.push({
fieldName: id,
valid: false,
data: null,
type: signatureType
});
const SignaturePadClass = Vue.extend(SignaturePad);
const SignaturePadInstance = new SignaturePadClass({
parent: this,
propsData: {
fieldName: id,
editable: true,
signatureType: signatureType,
signatureIndex: length - 1,
signatureData: null
}
});
// add handler for signed emit
SignaturePadInstance.$on('signed', signature => {
this.padSigned(signature);
});
// watch this for an accepted signature, then pass to each child
this.$watch('createdSignature.accepted', function (val) {
let signatureData = null;
if (val) {
signatureData = signatureType == 'signature' ? this.createdSignature.signatureData : this.createdSignature.initialsData;
}
// These two lines are the problem
SignaturePadInstance._props.signatureData = signatureData;
SignaturePadInstance._props.editable = !val;
});
SignaturePadInstance.$mount(element);
}
});
},

据我所知,propsData 现在是在组件上静态设置的。 但是对于signatureDataeditable道具,我需要能够在更新子组件时将其传递给子组件。 观察者工作正常,道具正在更新,但我收到Avoid mutating a prop directly警告。 这是可以理解的,因为我直接在孩子身上改变道具。有没有处理这个问题的好方法?

在我找到这个堆栈溢出答案之后,我能够弄清楚这一点。 在propsData上设置道具时,我使用了所有原始类型,因此它们没有内置的反应式吸气剂和设置器。 现在我意识到,我所做的相当于将字符串作为道具传递给组件元素,这是有道理的。 完成此操作后,道具是被动的,我不必费心手动创建观察者。

无论如何,这是解决方案:

const SignaturePadInstance = new SignaturePadClass({
parent: this,
propsData: {
fieldName: id, // << primitive
editable: true, // << primitive
signatureType: signatureType, // << primitive
signatureIndex: length - 1,  // << primitive
createdSignature: this.createdSignature  // << reactive object, updates to the child when changed
}
});

我使用 Vue.observable(VueJS 2.6 及更高版本(使属性具有响应性。下面是一个完整的示例:

initializeSignaturePad() {
const signaturePadComponent = Vue.extend(SignaturePad)
this.instance = new signaturePadComponent()
instance._props = Vue.observable({
...instance._props,
editable: true
})
this.instance.$mount()
document.body.appendChild(instance.$el)
}

onSignatureAccepted {
this.instance.editable = false
}

相关内容

最新更新