[Vue warn]: $attrs is readonly.

[Vue warn]: $attrs is readonly.

背景: 封装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...


回答:

我这边解决的方法 是 vue 和 vue-template-compiler的版本一致 就可以了

以上是 [Vue warn]: $attrs is readonly. 的全部内容, 来源链接: utcz.com/p/936052.html

回到顶部