写几个小案例来理解vue的组件化编程思想,下面是一个demo.
效果图示:
功能: Add组件用于添加用户评论,提交后右边评论回复会立马显示数据.Item组件点击删除可以删除当前用户评论.当List组件中用户评论为空时,会提示"暂无评论,点击左侧添加评论".
项目目录:
代码:
1.index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>vue_demo</title> <link rel="stylesheet" href="./static/css/bootstrap.css"> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>
2.main.js
import Vue from 'vue' import App from './App' new Vue({ el: '#app', components: { App }, template: '<App/>' })
3.App.vue
<template> <div> <header class="site-header jumbotron"> <div class="container"> <div class="row"> <div class="col-xs-12"> <h1>请发表对Vue的评论</h1> </div> </div> </div> </header> <div class="container"> <Add :addComment="addComment" /> <!-- 组件通信:属性名最好与model中一致(绑定表达式) --> <List :comments="comments" :deleteComment="deleteComment"/> </div> </div> </template> <script> import Add from './components/Add' import List from './components/List' export default { name: 'App', data(){ return { comments: [ // 数据在哪个组件,更新数据的行为(方法)就应该定义在哪个组件 { name: 'Jack', content: 'vue so easy' }, { name: 'Tom', content: 'vue so nice' }, { name: 'Cat', content: 'vue so cool' }, ], } }, methods: { // 添加评论 addComment (comment) { this.comments.unshift(comment) }, // 删除指定下标的评论 deleteComment (index) { this.comments.splice(index,1) } }, components: {Add ,List}, } </script> <style> </style>
4.Add.vue
<template> <div class="col-md-4"> <form class="form-horizontal"> <div class="form-group"> <label>用户名</label> <input type="text" class="form-control" placeholder="用户名" v-model="name"> </div> <div class="form-group"> <label>评论内容</label> <textarea class="form-control" rows="6" placeholder="评论内容" v-model="content"></textarea> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="button" class="btn btn-default pull-right" @click="add">提交</button> </div> </div> </form> </div> </template> <script> export default { name: "Add", props: { // 声明接受属性 addComment: { //指定属性名/属性值类型/必要性 type: Function, required: true } }, data () { return { name: '', content: '' } }, methods: { add () { // 1.检查输入的合法性 const name = this.name.trim() const content = this.content.trim() if (!name || !content) { alert('name和content不能为空') return } // 2.根据输入的数据,封装成一个comment对象 const comment = { name, content } // 3.添加到comments中 this.addComment(comment) // 4.清楚输入 this.name = '' this.content = '' } } } </script> <style scoped> </style>
5.List.vue
<template> <div class="col-md-8"> <h3 class="reply">评论回复:</h3> <h2 v-show="comments.length===0">暂无评论,点击左侧添加评论!!!</h2> <ul class="list-group"> <!-- 使用Item标签: 遍历数组,数组通信 --> <Item v-for="(comment,index) in comments" :key="index" :comment="comment" :deleteComment="deleteComment" :index="index"/> </ul> </div> </template> <script> // 引入Item组件 import Item from './Item' export default { name: "List", // 声明接受属性: 会成为组件对象的属性(类似与vm: data(){return {comments: []}}) props: ['comments','deleteComment'], //只指定属性名 components: { // 组件映射标签 Item } } </script> <style scoped> .reply { margin-top: 0px; } </style>
6.Item.vue
<template> <li class="list-group-item"> <div class="handle"> <a href="javascript:;" @click="deleteItem">删除</a> </div> <p class="user"><span >{{comment.name}}</span><span>说:</span></p> <p class="centence">{{comment.content}}</p> </li> </template> <script> export default { name: "Item", // 声明接受属性 props: { // 指定属性名和属性值的类型 comment: Object, deleteComment: Function, index: Number }, methods: { deleteItem () { const {comment,deleteComment,index} = this if (window.confirm(`是否确定删除${comment.name}的评论?`)) { deleteComment(index) } } } } </script> <style scoped> li { transition: .5s; overflow: hidden; } .handle { width: 40px; border: 1px solid #ccc; background: #fff; position: absolute; right: 10px; top: 1px; text-align: center; } .handle a { display: block; text-decoration: none; } .list-group-item .centence { padding: 0px 50px; } .user { font-size: 22px; } </style>