简单的vue 组件化demo,效果很简单,就是一个列表增删改查。
未组件化代码:
<!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>demo1</title>
<script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
</head>
<body class="container">
<div id="app">
<div class="row toolbar">
<div class="col-md-8">
keyword:
<input type="text" v-model="keyword" placeholder="title"/>
<input type="button" @click="query()" value="search" class="btn btn-primary"/>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="col-md-6">
<table class="table table-bordered">
<tr>
<th></th>
<th>title</th>
<th>desc</th>
<th></th>
</tr>
<tr v-for="(todoItem,index) in todolist">
<td>{{todoItem.id}}</td>
<td>{{todoItem.title}}</td>
<td>{{todoItem.desc}}</td>
<td>
<input type="button" value="remove" @click="remove(index)" class="btn btn-danger"/>
<input type="button" value="editor" @click="editor(todoItem.id)" class="btn btn-info"/>
</td>
</tr>
</table>
</div>
<div class="col-md-6">
<div class="form-inline">
<label for="title" class="control-label col-md-4">title:</label>
<!--<input type="text" v-model="title" class="form-control col-md-8">-->
<input type="hidden" v-bind:value="todoItem.id"/>
<input type="text" v-model="todoItem.title" class="form-control col-md-8">
</div>
<div class="form-inline">
<label for="desc" class="control-label col-md-4">desc</label>
<!--<input type="text" v-model="desc" class="form-control col-md-8">-->
<input type="text" v-model="todoItem.desc" class="form-control col-md-8">
</div>
<div class="form-inline">
<input type="button" value="OK" v-on:click="save()" class="btn btn-primary offset-md-10"
:disabled="canSave"/>
</div>
</div>
</div>
</div>
<script>
var list = [];
var todoItem = (function () {
var id = 1;
return function (title, desc) {
this.title = title;
this.desc = desc;
this.id = id++;
}
})();
new Vue({
el: '#app',
data: {
todolist: [],
todoItem: {
id: '',
title: '',
desc: ''
},
keyword:''
},
methods: {
save: function () {
if (this.todoItem.id) {
//编辑修改
var obj = this.todolist.filter(v => v.id === this.todoItem.id)[0];
obj.title = this.todoItem.title;
obj.desc = this.todoItem.desc;
} else {
//保存数据
this.todolist.push(new todoItem(this.todoItem.title, this.todoItem.desc))
}
//初始化输入框
this.todoItem = {title: '', desc: ''};
list = this.todolist;
},
editor: function (id) {
var obj = this.todolist.filter(v => v.id === id)[0];
this.todoItem = {
id: obj.id,
title: obj.title,
desc: obj.desc
}
},
remove: function (index) {
this.todolist.splice(index, 1);
list = this.todolist;
},
query:function(){
//过滤title中不包含keyword的数据
//这里必须通过list全局变量过滤,而不能通过this.todolist,因为需要给this.todolist赋值,赋值后无法还原原来的列表。
this.todolist = list.filter(v => v.title.indexOf(this.keyword) !== -1);
}
},
computed:{
//过滤
canSave: function () {
return !this.todoItem.title || !this.todoItem.desc
}
}
})
</script>
</body>
</html>
效果:
组件化后:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>demo1组件化</title>
<script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
</head>
<body class="container">
<div id="app">
<todo-container></todo-container>
</div>
<script>
;(function () {
var list = [];
var Todo = (function () {
var id = 1;
return function (title, desc) {
this.title = title;
this.desc = desc;
this.id = id++;
}
})();
//搜索框
var SearchBar = {
template : `<div class="row toolbar">
<div class="col-md-8">
keyword:
<input type="text" v-model="keyword" placeholder="title"/>
<input type="button" @click="search()" value="search" class="btn btn-primary"/>
</div>
</div>`,
data:function(){
return{
keyword:''
}
},
methods:{
search:function(){
this.$emit('onsearch',this.keyword);
}
}
};
//表单
var TodoForm = {
template : `<div class="col-md-6">
<div class="form-inline">
<label for="title" class="control-label col-md-4">title:</label>
<input type="hidden" v-bind:value="todo.id"/>
<input type="text" v-model="todo.title" class="form-control col-md-8">
</div>
<div class="form-inline">
<label for="desc" class="control-label col-md-4">desc:</label>
<input type="text" v-model="todo.desc" class="form-control col-md-8">
</div>
<div class="form-inline">
<input type="button" value="OK" v-on:click="save()" class="btn btn-primary offset-md-10"/>
</div>
</div>`,
props:['initItem'],
computed:{
todo:function(){
return {id:this.initItem.id,title:this.initItem.title,desc:this.initItem.desc}
}
},
methods:{
save:function(){
this.$emit('onsave',this.todo);
}
}
};
//列表项组件
var TodoItem = {
template : `<tr>
<td>{{todo.id}}</td>
<td>{{todo.title}}</td>
<td>{{todo.desc}}</td>
<td>
<input type="button" value="remove" @click="remove()" class="btn btn-danger"/>
<input type="button" value="editor" @click="editor()" class="btn btn-info"/>
</td>
</tr>`,
props:['todo'],
methods:{
remove:function(){
this.$emit('onremove',this.todo.id)
},
editor:function(){
this.$emit('oneditor',this.todo.id)
}
}
};
//列表组件
var TodoList = {
template : `
<div class="col-md-6">
<table class="table table-bordered">
<tr>
<th></th>
<th>title</th>
<th>desc</th>
<th></th>
</tr>
<todo-item v-for="item in items" :todo="item" :key="item.id" @onremove="remove($event)" @oneditor="editor($event)"></todo-item>
</table>
</div>
`,
props:['items'],
components:{
'todo-item':TodoItem
},
methods:{
remove:function($e){
this.$emit('onremove',$e)
},
editor:function($e){
this.$emit('oneditor',$e)
}
}
};
//主组件
//主组件中,通过:items和:init-item将数据传递到子组件中,子组件通过props接受并直接使用;通过@onsearch,@onremove,@ondeitor,@onsave,将对应操作事件的逻辑传递给子组件,子组件通过$emit接收并返回操作执行后的结果到主组件上进行显示
var TodoContainer = {
template : `<div id="container">
<search-bar @onsearch="search($event)"></search-bar>
<div class="row" style="margin-top:10px;">
<todo-list :items="items" @onremove="remove($event)" @oneditor="editor($event)"></todo-list>
<todo-form :init-item="initItem" @onsave="save($event)"></todo-form>
</div>
</div>`,
data: function () {
return {
items: [],
initItem: {
title: '',
desc: '',
id: ''
}
}
},
components: {
'search-bar': SearchBar,
'todo-list': TodoList,
'todo-form': TodoForm
},
methods: {
/**
* 模拟保存数据方法
* 辅助方法
*/
_mock_save: function (lst) {
list = lst
},
/**
* 根据id查询对象
* 辅助方法
*/
findById: function (id) {
return this.items.filter(v => v.id === id)[0] || {};
},
/**
* 查询方法
* 由SearchBar组件触发
*/
search: function ($e) {
this.items = list.filter(v => v.title.indexOf($e) !== -1);
},
/**
* 保存方法
* 响应新增和更新操作,由TodoForm组件触发
*/
save: function ($e) {
if (this.initItem.id) {
//更新
var obj = this.findById($e.id);
obj.title = $e.title;
obj.desc = $e.desc;
} else {
//新增
this.items.push(new Todo($e.title,$e.desc))
}
//重置
this.initItem = {
title: '',
desc: '',
id: ''
};
//更新数据列表
this._mock_save(this.items)
},
/**
* 删除方法
* 响应删除按钮操作
* 由TodoItem组件触发
*/
remove:function($e){
this.items = this.items.filter(v => v.id !== $e)
this._mock_save(this.items)
},
/**
* 编辑按钮点击时,进行表单数据绑定
*/
editor:function($e){
this.initItem = this.findById($e);
}
}
};
var app = new Vue({
el: '#app',
components: {
'todo-container': TodoContainer
}
});
})();
</script>
</body>
</html>
效果:
详细见解请移步原贴:http://www.cnblogs.com/Johnzhang/p/7208682.html#3787902