声明:文中代码整体思路来源于 梁灏 编著的 【Vue.JS 实战】一书,学习过程中发现一处问题。以做记录
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>BBStitle>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
head>
<body>
<div id="demo" v-cloak style="width:500px;margin:0 auto">
<div class="message">
<v-input v-model="username">v-input>
<v-textarea v-model="message" ref="message">v-textarea>
<button @click="handleSend">发送button>
div>
<list :list="list" @reply="handleReply">list>
div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js">script>
<script src="input.js">script>
<script src="list.js">script>
<script src="main.js">script>
body>
html>
var demo = new Vue({
el: '#demo',
data: {
username: '',
message: '',
list: []
},
methods: {
handleSend() {
if (this.username === '' || this.message === '') {
alert('不能为空');
return;
}
this.list.push({
username: this.username,
message: this.message,
});
this.message = '';
},
handleReply(index) {
var name = this.list[index].username;
this.message = "回复@" + name + ':';
this.$refs.message.focus();
}
},
})
Vue.component('vInput', {
props: {
value: {
type: [String, Number],
default: ''
}
},
render: function (createElement) {
var _this = this;
return createElement('div', [
createElement('span', '昵称:'),
createElement('input', {
attrs: {
type: 'text'
},
domProps: {
value: this.value,
},
on: {
input: function (event) {
_this.value = event.target.value;
_this.$emit('input', event.target.value);
}
}
})
]);
}
});
Vue.component('vTextarea', {
props: {
value: {
type: [String, Object],
default: '',
}
},
render: function (createElement) {
var _this = this;
return createElement('div', [
createElement('span', '留言内容:'),
createElement('textarea', {
attrs: {
placeholder: '请输入内容',
},
domProps: {
value: this.value,
},
ref: 'message',
on: {
input: function (event) {
//_this.value = event.target.value;
_this.$emit('input', event.target.value);
}
}
})
])
},
methods: {
focus: function () {
this.$refs.message.focus();
}
},
})
Vue.component('list', {
props: {
list: {
type: [Array],
default: function () {
return [];
}
}
},
render: function (createElement) {
var _this = this;
var list = [];
this.list.forEach((item, index) => {
var node = createElement('div', {
attrs: {
class: 'list-item',
}
}, [
createElement('span', item.username + ':'),
createElement('div', {
attrs: {
class: 'list-msg',
}
}, [
createElement('p', item.message),
createElement('a', {
attrs: {
class: 'list-reply'
},
on: {
click: function () {
_this.handleReply(index);
}
},
}, '回复'),
])
]);
list.push(node);
});
if (this.list.length) {
return createElement('div', {
attrs: {
class: 'list',
},
}, list);
} else {
return createElement('div', {
attrs: {
class: 'list-nothing',
}
}, '列表为空')
}
},
methods: {
handleReply: function (index) {
this.$emit('reply', index);
}
},
})
[v-cloak] {
display: none;
}
* {
padding: 0;
margin: 0;
}
.message {
width: 450px;
text-align: right;
}
.message div {
margin-bottom: 12px;
}
.message span {
display: inline-block;
width: 100px;
vertical-align: top;
}
.message input,
.message textarea {
width: 300px;
height: 32px;
padding: 0 6px;
color: #657180;
border: 1px solid #d7dde4;
border-radius: 4px;
cursor: text;
outline: none;
}
.message input:focus,
.message textarea:focus {
border: 1px solid #3399FF;
}
.message textarea {
height: 60px;
padding: 4px 6px;
}
.message button {
display: inline-block;
padding: 6px 15px;
border: 1px solid #39F;
border-radius: 4px;
color: #FFF;
background-color: #39F;
cursor: pointer;
outline: none;
}
.list {
margin-top: 50px;
}
.list-item {
padding: 10px;
border-bottom: 1px solid #e3e8ee;
overflow: hidden;
}
.list-item span {
display: block;
width: 120px;
float: left;
color: #39F;
}
.list-msg {
display: block;
margin-left: 60px;
text-align: justify;
}
.list-msg a {
color: #9ea7b4;
cursor: pointer;
float: right;
}
.list-msg a:hover {
color: #39F;
}
.list-nothing {
text-align: center;
color: #9ea7b4;
padding: 20px;
}
虽然标记的是 Vue warn ,仅仅是警告,而且也没有影响到功能的使用,但显示成红色的 Error 总归有些不爽的。
于是,开始查找原因 …
发现是 由于 input.js 中监听 input 事件时 _this.value = event.target.value; 这一行代码引起的错误。
查阅本书之前对组件传值的描述,并结合Vue的官方文档,得出问题原因如下:
也就是说,报错的根本原因是 _this.value = event.target.value; 这一句话在子组件中对父组件的 value 进行了赋值操作,这在 Vue 2.X 中是不被允许的。
首先要分析是否的确需要在子组件中更新父组件的值。
render: function (createElement) {
......
on: {
input: function (event) {
_this.$emit('input', event.target.value);
}
}
}
Vue.component('vInput', {
props: {
value: {
type: [String, Number],
default: ''
}
},
data(){
return{
text : this.value,
}
},
render: function (createElement) {
......
on: {
input: function (event) {
_this.text = event.target.value;
}
}
}
....