背景: 封装confirm组件,当点击按钮弹出confirm时,报错[Vue warn]: $attrs is readonly.$listeners is readonly.第一次的时候不会出现,点击第二次第三次累加出现报错。使用方式this.$Confirm.error({xxxx})使用
vue@2.6.14版本
<script>
// component.vue
import Vue from 'vue';
import Modal from '../modal';
const timestamp = new Date().getMilliseconds();
let count = 0;
const Confirm = {
name: 'confirm',
components: {
Modal
},
props: {
value: {
type: Boolean,
default: false
},
modalProps: {
type: Object,
default() {
return {};
}
},
title: {
type: String,
default: '提示'
},
icon: String,
color: String,
content: [String, Function]
},
data() {
return {
visible: this.value
};
},
watch: {
value(v) {
this.visible = v;
},
visible(v) {
this.$emit('input', v);
}
},
methods: {
onInput(v) {
this.visible = v;
},
onConfirm() {
this.$emit('confirm');
},
onCancel() {
this.$emit('cancel');
}
},
render(h) {
const {
visible,
modalProps,
title,
icon,
color,
content,
$slots
} = this;
const node = typeof content === 'string' ? content : content(h);
return (
<modal
title={title}
width={450}
{...{ props: modalProps }}
value={visible}
on-input={this.onInput}
on-confirm={this.onConfirm}
on-cancel={this.onCancel}
>
<div class="mc-confirm-body">
<div class="mc-confirm-text">{ $slots.default || node }</div>
</div>
</modal>
);
}
};
const Popup = {
name: 'PopUp',
components: {
Confirm
},
props: {
popupClass: String,
Component: {}
},
data() {
return {
popups: [],
colorMap: {
info: 'info',
success: 'success',
error: 'error',
warning: 'warning '
},
iconMap: {
info: 'info-circle-o',
success: 'check-circle-',
error: 'close-circle-o',
warning: 'exclamation-circle-o '
}
};
},
methods: {
add(props) {
count++;
props.name = props.name || `${timestamp}-${count}`;
this.popups.push(props);
return () => {
this.close(props.name);
};
},
close(name) {
let index = -1;
this.popups.forEach((item, i) => {
if (item.name === name) {
index = i;
}
});
if (index !== -1) {
this.popups.splice(index, 1);
}
},
closeAll() {
this.popups = [];
}
},
render() {
const {
popupClass,
popups,
colorMap,
iconMap
} = this;
const fn = () => {};
const nodes = popups.map((item, i) => {
item.color = colorMap[item.type];
item.icon = item.icon || iconMap[item.type];
return (
<confirm
{...{ props: item }}
value={item.value}
key={i}
on-confirm={item.onOk || fn}
on-cancel={item.onCancel || fn}
>
{ item.content }
</confirm>
);
});
return (
<div
class={popupClass}
>{nodes}</div>
);
}
};
Confirm.createWrapper = (props = {}) => {
const Instance = new Vue({
render(h) {
return h(Popup, {
props: props
});
}
});
const popup = Instance.$mount();
document.body.appendChild(popup.$el);
return Instance.$children[0];
};
export default Confirm;
</script>
index.js
Confirm.install = function (Vue) {
const types = ['info', 'success', 'error', 'warning'];
types.forEach(type => {
Confirm[type] = xxx;
Confirm.confirm = xxxx;
Confirm.closeAll =xxxx;
Vue.prototype.$Confirm = Confirm;
Vue.component(Confirm.name, Confirm);
};
export default Confirm;
可能因为封装的组件内使用的Vue和组件外使用的Vue不是同一个,具体的网上很多
https://segmentfault.com/q/10...