Render函数:留言列表组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="Vue.2.6.10.js"></script>
</head>
<style>
[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 #e3e833;
overflow: hidden;
}
.list-item span{
display: block;
width: 60px;
float: left;
color:#39f;
}
.list-msg{
display: block;
width: 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;
}
</style>
<body>
<div id="app" v-cloak style="width: 500px;margin:0 auto; margin-top: 30px;">
<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>
</body>
<script>
Vue.component('vInput',{
props:{
value:{
type:[String,Number],
default:''
}
},
render(h) {
var _this = this;
return h('div',[
h('span','昵称:'),
h('input',{
attrs:{
type:'text'
},
domProps:{
value:this.value
},
on:{
//v-model在render中需要自己实现嗷
input:function(event){
_this.value = event.target.value;
_this.$emit('input',event.target.value)
}
}
})
])
},
});
Vue.component('vTextarea',{
props:{
value:{
type:String,
default:''
}
},
render(h) {
var _this = this;
return h('div',[
h('span','留言内容'),
h('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(h) {
var _this = this;
var list = [];
this.list.forEach(function(msg,index){
var node = h('div',{
attrs:{
class:'list-item'
}
},[
h('span',msg.name + ":"),
h('div',{
attrs:{
class:'list-msg'
}
},[
h('p',msg.message),
h('a',{
attrs:{
class:'list-reply'
},
on:{
click:function(){
_this.handleReply(index);
}
}
},'回复')
])
])
list.push(node);
});
if(this.list.length){
return h('div',{
attrs:{
class:'list'
},
},list);
}else{
return h('div',{
attrs:{
class:'list-nothing'
},
},'留言列表为空嗷,说点什么吧~')
}
},
methods:{
handleReply:function(index){
this.$emit('reply',index);
}
}
});
//发布留言需要的数据主要有:昵称、留言内容,发布操作在根实例内完成,留言列表数据同样获取自app
var app = new Vue({
el:"#app",
data:{
username:'',
message:'',
list:[]
},
methods: {
handleSend:function(){
if(this.username === ''){
window.alert('要输入昵称噢');
return
}
if(this.message === ''){
window.alert('说点什么吧~');
return
}
this.list.push({
//List是一个对象数组?
name:this.username,
message:this.message
});
console.log(this.list);
this.message = '';//置空输入栏
},
handleReply:function(index){
var name = this.list[index].name;
this.message = '回复@' + name + ":";
this.$refs.message.focus();
}
},
});
//分析一哈:
//v-input组件:生成<span>昵称</span>与输入栏,
// 并设置输入栏的值为这个组件得到的值:在render函数中用on选项实现v-model
//(需要domPropsyuon配合来实现双向绑定)当触发input事件,将v-input组件的value更新为
//同时向根实例发送一个input事件
//v-textarea组件:生成<span>留言内容<span>与文本输入域,在这里同样手动实现v-model
//该组件中多包含了一个focus方法,this.$refs.message.focus()使得这个实例中render函数生成的textarea获得焦点
//点击回复按钮,调用handleSend(),将昵称与留言内容传入list,置空输入栏,
//▲list组件
//接收到list后,使用list来渲染留言列表,同时在‘回复’按钮上传入昵称对应的index,当点击时调用handleReply方法
//它的reply方法是为了调用根实例的同名方法
//
</script>
</html>
预览效果:
这几个Vue的小组件写下来,写的我真的好佩服尤大...