vue part3.1 小案例 comments评论页
步骤概要
设计步骤
- 拆分组件 (可以先准备好完整的bootstrap美化页面,然后切分)
- 静态组件
- 动态组件
软件编写步骤
- 准备静态文件 (含bootstrap等)
- 编写 vue webpacke
案例1:comment
1. 静态页面 与拆分
静态页面
先设计html 如 bootstrap css美化过的页面
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="stylesheet" href="./static/css/bootstrap.css"> <title>vue_demo</title> </head> <body> <div id="app"> <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"> <div class="col-md-4"> <form action="form-horizontal"> <div class="form-group"> <label>用户名</label> <input type="text" class="form-control" placeholder="用户名"> </div> <div class="form-group"> <label>评论内容</label> <textarea type="text" class="form-control" placeholder="评论内容"></textarea> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="button" class="btn btn-default pull-right">提交</button> </div> </div> </form> </div> <!--md4 for Add end --> <div class="col-md-8"> <h3 class="reply">评论回复:</h3> <h2>暂无评论,点击左侧添加评论吧!</h2> <ul class="list-group"> <li class="list-group-item"> <div class="handle"> <a>删除</a> </div> <p class="user"><span>Tom</span><span>说:</span></p> <p class="centence">jerry是猫</p> </li> </ul> </div> <!--md8 for List end --> </div> </div> </div> <!--app --> </body> </html>
页面拆分
红框含app,内部黄框为整体App.vue
绿框分割
其中header标记是html5 新标记http://know.webhek.com/html5/html5-header.html
2.代码过程
2.1代码静态分割
main.js
/** * Created by infaa on 2018/9/18. */ import Vue from 'vue' import App from './App' /* eslint-disable no-new */ new Vue({ el: '#app', template: '<App/>', components: {App} })
App.uve
<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/> <List/> </div> </div> </template> <script> import Add from './components/Add.vue' import List from './components/List.vue' export default { components: { Add, List } } </script> <style> </style>
./components/Add.vue
components 实际复杂情况下为目录,每个目录为完整一组功能,含图片等元素。
<template> <div class="col-md-4"> <form action="form-horizontal"> <div class="form-group"> <label>用户名</label> <input type="text" class="form-control" placeholder="用户名"> </div> <div class="form-group"> <label>评论内容</label> <textarea type="text" class="form-control" placeholder="评论内容"></textarea> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="button" class="btn btn-default pull-right">提交</button> </div> </div> </form> </div> <!--md4 for Add end --> </template> <script> export default { } </script> <style> </style>
./components/List.vue
<template> <div class="col-md-8"> <h3 class="reply">评论回复:</h3> <h2>暂无评论,点击左侧添加评论吧!</h2> <ul class="list-group"> <li class="list-group-item"> <div class="handle"> <a>删除</a> </div> <p class="user"><span>Tom</span><span>说:</span></p> <p class="centence">jerry是猫</p> </li> </ul> </div> <!--md8 for List end --> </template> <script> export default { } </script> <style> </style>
2.2 代码动态传递(父组件->子组件->子组件)
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 :comments="comments"/> <List :comments="comments"/> </div> </div> </template> <script> import Add from './components/Add.vue' import List from './components/List.vue' export default { components: { Add, List }, data () { return { comments: [ { name: 'bob', content: 'Vue of bobaaaaaaaaaaaaaaaaaaaaaaaaaaa' }, { name: 'cat', content: 'VUE OF CAT' }, { name: 'david', content: 'vue of davie' } ] } } } </script> <style> </style>
list.uve
components引入子组件,props申明父组件变量,:comment通过属性向子组件传递 。 以上过程可以多次传递
<template> <div class="col-md-8"> <h3 class="reply">评论回复:</h3> <h2>暂无评论,点击左侧添加评论吧!</h2> <ul class="list-group" > <item v-for="(comment,index) in comments" :key="index" :comment="comment"></item> </ul> </div> <!--md8 for List end --> </template> <script> import Item from './Item.vue' export default { props: ['comments'], components: {Item} } </script> <style> .reply { margin-top: 0px; } li { transition: .5s; overflow: hidden; } .handle a { display: block; text-decoration: none; } </style>
item.vue
测试再向内传递comment值
<template> <li class="list-group-item"> <div class="handle"> <a>删除</a> </div> <p class="user"><span>{{comment.name}}</span><span>说:</span></p> <p class="centence">{{comment.content}}</p> <Item2 :comment="comment"></Item2> </li> </template> <script> import Item2 from './Item2.vue' export default { props: {'comment': Object}, components: {Item2} } </script> <style> 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>
item2.vue
<template> <span :comment="comment">多次传递实例{{comment.content}}</span> </template> <script> export default { props:['comment'] } </script> <style> </style>
2.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" /> <List :comments="comments" :deleteComment="deleteComment"/> </div> </div> </template> <script> import Add from './components/Add.vue' import List from './components/List.vue' export default { components: { Add, List }, data () { return { comments: [ { name: 'bob', content: 'Vue of bobaaaaaaaaaaaaaaaaaaaaaaaaaaa' }, { name: 'cat', content: 'VUE OF CAT' }, { name: 'david', content: 'vue of davie' } ] } }, // 数据在哪里,就在哪里定义方法 methods: { addComment (comment) { this.comments.unshift(comment) }, deleteComment (index) { this.comments.splice(index, 1) } } } </script> <style> </style>
list.vue
<template> <div class="col-md-8"> <h3 class="reply">评论回复:</h3> <h2 v-show="comments.length===0">暂无评论,点击左侧添加评论吧!</h2> <ul class="list-group" > <item v-for="(comment,index) in comments" :index="index" :deleteComment="deleteComment" :comment="comment" :key="index"></item> </ul> </div> <!--md8 for List end --> </template> <script> import Item from './Item.vue' export default { props: ['comments', 'deleteComment'], components: {Item} } </script> <style> .reply { margin-top: 0px; } li { transition: .5s; overflow: hidden; } .handle a { display: block; text-decoration: none; } </style>
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 { props: { 'comment': Object, 'deleteComment': Function, 'index': Number }, methods: { deleteItem () { const {comment, index, deleteComment} = this if (window.confirm(`确定删除${comment.name}的评论吗`)) { deleteComment(index) } } } } </script> <style> 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>
add.vue
<template> <div class="col-md-4"> <form action="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 type="text" class="form-control" 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> <!--md4 for Add end --> </template> <script> export default { props: { addComment: { type: Function, required: true } }, data () { return { name: '', content: '' } }, methods: { add () { const name = this.name.trim() const content = this.content if (!name || !content) { alert('no name or content') return } const comment = { name, content } this.addComment(comment) // 清除输入 this.name = '' this.content = '' } } } </script> <style> </style>
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="stylesheet" href="./static/css/bootstrap.css"> <title>vue_demo</title> </head> <body> <div id="app"> </div> <!--app --> </body> </html>
main.js
/** * Created by infaa on 2018/9/18. */ import Vue from 'vue' import App from './App' /* eslint-disable no-new */ new Vue({ el: '#app', template: '<App/>', components: {App} })
参考
https://github.com/sunny-sky/VueDemo