Vue ③

1. 基于脚手架编写项目

打开vue_demo

1.1 初始化显示

在这里插入图片描述

**加粗样式**

组件之间的通信 props

App.vue
template 内是它负责的部分
script 引入其他组件 import component



<!--  -->
<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 :comments="comments"/>
    
    </div>
  </div>
</template>

<script>
  import Add from './components/Add.vue'
  import List from './components/List.vue'
export default {
  data(){
    return {
      comments:[
        {
          name:'张三',
          content:'Vue soso'
        },
         {
          name:'张王',
          content:'Vue easy'
        },
         {
          name:'张飞',
          content:'Vue good'
        }
      ]
    }
  },
    components: {
      Add,List  
    }
};
</script>
<style>
</style>

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="用户名">
          </div>
          <div class="form-group">
            <label>评论内容</label>
            <textarea class="form-control" rows="6" 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>
</template>

<script>
export default {
    
};
</script>
<style>

</style>

List.vue
接收 属性值 comments
引入声明其他组件item

<!--  -->
<template>
   <div class="col-md-8">
        <h3 class="reply">评论回复:</h3>
        <h2 style='display: none'>暂无评论,点击左侧添加评论!!!</h2>
        <ul class="list-group">
          <Item :comment="comment" v-for="(comment,index) in comments" :key="index"/>
        </ul>
      </div>
</template>

<script>
 import Item from './Item.vue'
export default {
  //声明接收属性:这个属性就是成为组件对象的属性
  props:['comments'],//只指定属性名
  components: {
    Item
  }
};
</script>
<style>
 .reply {
  margin-top: 0px;
}

</style>

Item.vue

<!--  -->
<template>
    <div>
       <li class="list-group-item">
            <div class="handle">
              <a href="javascript:;">删除</a>
            </div>
            <p class="user"><span >{{comment.name}}</span><span>说:</span></p>
            <p class="centence">{{comment.content}}</p>
          </li>
    </div>
</template>

<script>
export default {
    props: {
        comment:Object//指定属性名和属性值类型
    }
};
</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>

在这里插入图片描述

1.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 :addComment="addComment"/>
      <List :comments="comments"/>
    
    </div>
  </div>
</template>

<script>
  import Add from './components/Add.vue'
  import List from './components/List.vue'
export default {
 
  data(){
    return {
      comments:[//数据在那个组件更新数据的行为就该在那个组件
        {
          name:'张三',
          content:'Vue soso'
        },
         {
          name:'张王',
          content:'Vue easy'
        },
         {
          name:'张飞',
          content:'Vue good'
        }
      ]
    }
  },
  methods: {
    addComment(comment){
      this.comments.unshift(comment)
    }
  },
    components: {
      Add,List  
    }
};
</script>
<style>
</style>

props: {
addComment:{//指定属性名/属性值类型/必要性
type:Function,
required:true
}
},

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 {
   props: {
    addComment:{//指定属性名/属性值类型/必要性
        type:Function,
        required:true
    }
  },
    data () {
      return {
        name:'',
        contentt:''
      }
    },
    methods: {
      add(){
        //1.检查输入内容的合法性
        const name=this.name.trim()
        const content=this.content.trim()
        if(!name||!content)
        {
          alert('姓名或内容不为空')
          return
        }
        //2.根据输入的内容封装成comment对象
        const comment={
          name,
          content
        }
        //3.添加到comments
        this.addComment(comment)
        //4.清除输入
        this.name=''
        this.content=''
      }
    }
};
</script>
<style>

</style>

1.3 删除

在App中实现删除方法 之后传递到list里面

<!--  -->
<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 {
 
  data(){
    return {
      comments:[//数据在那个组件更新数据的行为就该在那个组件
        {
          name:'张三',
          content:'Vue soso'
        },
         {
          name:'张王',
          content:'Vue easy'
        },
         {
          name:'张飞',
          content:'Vue good'
        }
      ]
    }
  },
  methods: {
    //添加评论
    addComment(comment){
      this.comments.unshift(comment)
    },
    //删除指定下标评论
    deleteComment(index)
    {
      this.comments.splice(index,1)
    }
  },
    components: {
      Add,List  
    }
};
</script>
<style>
</style>

List中声明传递的方法,再向item传递方法下标

重点看item标签

<!--  -->
<template>
   <div class="col-md-8">
        <h3 class="reply">评论回复:</h3>
        <h2 v-show="comments.length==0">暂无评论,点击左侧添加评论!!!</h2>
        <ul class="list-group">
          <Item :comment="comment" v-for="(comment,index) in comments" :key="index" :deleteComment="deleteComment" :index="index"/>
        </ul>
      </div>
</template>

<script>
 import Item from './Item.vue'
export default {
  //声明接收属性:这个属性就是成为组件对象的属性
  props:['comments','deleteComment'],//只指定属性名
  components: {
    Item
  }
};
</script>
<style>
 .reply {
  margin-top: 0px;
}

</style>

item中实现deleteItem方法调用的是deleteComment方法,声明传递过来的东西

<!--  -->
<template>
    <div>
       <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>
    </div>
</template>

<script>
export default {
    props: {
        comment:Object,//指定属性名和属性值类型
        deleteComment:Function,
        index:Number
    },
    methods: {
      deleteItem(){
        const{comment,index,deleteComment}=this
        if(window.confirm(`确定删除${comment.name}的评论吗?`))
        {
            this.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>

在这里插入图片描述在这里插入图片描述

2.案例二

2.1 初始化显示

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>React App</title>

  <link rel="stylesheet" href="index.css">
</head>
<body>
<div id="root">
  <div class="todo-container">
    <div class="todo-wrap">
      <div class="todo-header">
        <input type="text" placeholder="请输入你的任务名称,按回车键确认"/>
      </div>
      <ul class="todo-main">
        <li>
          <label>
            <input type="checkbox"/>
            <span>xxxxx</span>
          </label>
          <button class="btn btn-danger" style="display:none">删除</button>
        </li>
        <li>
          <label>
            <input type="checkbox"/>
            <span>yyyy</span>
          </label>
          <button class="btn btn-danger" style="display:none">删除</button>
        </li>
      </ul>
      <div class="todo-footer">
        <label>
          <input type="checkbox"/>
        </label>
        <span>
          <span>已完成0</span> / 全部2
        </span>
        <button class="btn btn-danger">清除已完成任务</button>
      </div>
    </div>
  </div>
</div>

</body>
</html>

在这里插入图片描述
将其划分成五部分:

在这里插入图片描述
在这里插入图片描述

App.vue
导入其他组件 写入标签 初始化数据 将数据传到List

<!--  -->
<template>
    <div id="root">
        <div class="todo-container">
            <div class="todo-wrap">
                <Header />
                <Footer />
                <List :todos="todos"/>
            </div>
        </div>
    </div>
</template>
<script>
import Header from "./components/Header.vue";
import Footer from "./components/Footer.vue";
import List from "./components/List.vue";
export default {
    data() {
        return {
            todos: [
                { title: "写英语", complete: false },
                { title: "读语文", complete: false },
                { title: "打球", complete: false },
                { title: "理发", complete: false },
            ],
        };
    },
    components: {
        Header,
        Footer,
        List,
    },
};
</script>
<style>
.todo-container {
    width: 600px;
    margin: 0 auto;
}
.todo-container .todo-wrap {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
}
</style>

List.vue
声明传来的数据 声明组件item 导入 写标签 传值

<!--  -->
<template>
  <ul class="todo-main">
        <Item v-for="(todo,index) in todos" :key="index" :todo="todo" :index="index"/>
  </ul>
</template>

<script>
  import Item from './Item.vue'
export default 
{
    props:
    {
      todos:Array
    },
    components: {
      Item
    }
}
</script>

<style>
.todo-main {
    margin-left: 0px;
    border: 1px solid #ddd;
    border-radius: 2px;
    padding: 0px;
  }
  
  .todo-empty {
    height: 40px;
    line-height: 40px;
    border: 1px solid #ddd;
    border-radius: 2px;
    padding-left: 5px;
    margin-top: 10px;
  }
  
</style>
<!--  -->
<template>
        <li>
          <label>
            <input type="checkbox" v-model="todo.complete"/>
            <span>{{todo.title}}</span>
          </label>
          <button class="btn btn-danger" style="display:none">删除</button>
        </li>
</template>

<script>

export default {
    props: {
        todo:Object,
        index:Number
    }
}
</script>

<style>
/*item*/
  li {
    list-style: none;
    height: 36px;
    line-height: 36px;
    padding: 0 5px;
    border-bottom: 1px solid #ddd;
  }
  
  li label {
    float: left;
    cursor: pointer;
  }
  
  li label li input {
    vertical-align: middle;
    margin-right: 6px;
    position: relative;
    top: -1px;
  }
  
  li button {
    float: right;
    display: none;
    margin-top: 3px;
  }
  
  li:before {
    content: initial;
  }
  
  li:last-child {
    border-bottom: none;
  }
  
</style>

2.2 添加

首先在App中 写一个方法是用来添加数据的 之后传到Header中

<!--  -->
<template>
    <div id="root">
        <div class="todo-container">
            <div class="todo-wrap">
                <Header :addTodo="addTodo"/>
            
                <List :todos="todos"/>
                   <Footer />
            </div>
        </div>
    </div>
</template>
<script>
import Header from "./components/Header.vue";
import Footer from "./components/Footer.vue";
import List from "./components/List.vue";
export default {
    data() {
        return {
            todos: [
                { title: "写英语", complete: false },
                { title: "读语文", complete: false },
                { title: "打球", complete: false },
                { title: "理发", complete: false },
            ],
        };
    },
    components: {
        Header,
        Footer,
        List,
    },
    methods: {
        addTodo(todo){
            this.todos.unshift(todo)
        }
    }
};
</script>
<style>
.todo-container {
    width: 600px;
    margin: 0 auto;
}
.todo-container .todo-wrap {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
}
</style>

在header中需要声明 传递来的方法 之后给input添加数据绑定 title 加上监听事件 ,实现add方法

<!--  -->
<template>
    <div class="todo-header">
        <input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="title" @keyup.enter="addItem" />
    </div>
</template>

<script>

export default 
{
  props: {
    addTodo:Function
  },
    data () {
      return {
        title:''
      }
    },
    methods: {
      addItem(){
         //检查输入的合法性
         const title=this.title.trim()
         if(!title)
         {
           alert('不能为空')
           return 
         }
         //生成todo对象
         const todo={
           title,complete:false
         }
         //添加到数组中
          this.addTodo(todo)
          //清除输入
          this.title=''
      }  
    }
}
</script>

<style>
.todo-header input {
    width: 560px;
    height: 28px;
    font-size: 14px;
    border: 1px solid #ccc;
    border-radius: 4px;
    padding: 4px 7px;
}

.todo-header input:focus {
    outline: none;
    border-color: rgba(82, 168, 236, 0.8);
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
        0 0 8px rgba(82, 168, 236, 0.6);
}
</style>

2.3 删除

首先 当鼠标移入到item时 显示出来删除按钮切背景颜色改变

<li @mouseenter="handleShow(true)" @mouseleave="handleShow(false)" 
:style="{background:bgColor}">
  methods: {
      handleShow(isEnter)
      {
        if(isEnter)
        {
          this.bgColor='rgb(217,220,217)'
          this.isShow=true;
        }else
        {
            this.bgColor='white'
          this.isShow=false;
        }
      }
    }

在这里插入图片描述

其次给删除按钮绑定删除事件

    <button class="btn btn-danger" v-show="isShow" @click="deleteItem">删除</button>

要想删除 首先在 App里面实现删除 并传递到list-item

  <List :todos="todos" :deleteTodo="deleteTodo"/>
	 methods: 
	 {
        deleteTodo(index)
        {
            this.todos.splice(index,1)
        }
    }

在item中实现删除方法

 deleteItem()
      {
        const {todo,index,deleteTodo}=this
        if(window.confirm(`确认删除${todo.title}?`))
        {
              deleteTodo(index)
        }

      }

item.vue

<!--  -->
<template>
        <li @mouseenter="handleShow(true)" @mouseleave="handleShow(false)" :style="{background:bgColor}">
          <label>
            <input type="checkbox" v-model="todo.complete"/>
            <span>{{todo.title}}</span>
          </label>
          <button class="btn btn-danger" v-show="isShow" @click="deleteItem">删除</button>
        </li>
</template>
<script>

export default {
    props: {
        todo:Object,
        index:Number,
        deleteTodo:Function
    },
    data () {
      return {
        bgColor:'white',
        isShow:false
      }
    },
    methods: {
      handleShow(isEnter)
      {
        if(isEnter)
        {
          this.bgColor='rgb(217,220,217)'
          this.isShow=true;
        }else{
            this.bgColor='white'
          this.isShow=false;
        }
      },
      deleteItem()
      {
        const {todo,index,deleteTodo}=this
        if(window.confirm(`确认删除${todo.title}`))
        {
              deleteTodo(index)
        }

      }
    }
}
</script>

<style>
/*item*/
  li {
    list-style: none;
    height: 36px;
    line-height: 36px;
    padding: 0 5px;
    border-bottom: 1px solid #ddd;
  }
  
  li label {
    float: left;
    cursor: pointer;
  }
  
  li label li input {
    vertical-align: middle;
    margin-right: 6px;
    position: relative;
    top: -1px;
  }
  
  li button {
    float: right;
    display: none;
    margin-top: 3px;
  }
  
  li:before {
    content: initial;
  }
  
  li:last-child {
    border-bottom: none;
  }
  
</style>

List.vue

<!--  -->
<template>
  <ul class="todo-main">
        <Item v-for="(todo,index) in todos" :key="index" :todo="todo" :index="index" :deleteTodo="deleteTodo"/>
  </ul>
</template>

<script>
  import Item from './Item.vue'
export default 
{
    props:
    {
      todos:Array,
      deleteTodo:Function
    },
    components: {
      Item
    }
}
</script>

<style>
.todo-main {
    margin-left: 0px;
    border: 1px solid #ddd;
    border-radius: 2px;
    padding: 0px;
  }
  
  .todo-empty {
    height: 40px;
    line-height: 40px;
    border: 1px solid #ddd;
    border-radius: 2px;
    padding-left: 5px;
    margin-top: 10px;
  }
  
</style>

App.vue

<!--  -->
<template>
    <div id="root">
        <div class="todo-container">
            <div class="todo-wrap">
                <Header :addTodo="addTodo"/>
            
                <List :todos="todos" :deleteTodo="deleteTodo"/>
                <Footer />
            </div>
        </div>
    </div>
</template>
<script>
import Header from "./components/Header.vue";
import Footer from "./components/Footer.vue";
import List from "./components/List.vue";
export default {
    data() {
        return {
            todos: [
                { title: "写英语", complete: false },
                { title: "读语文", complete: false },
                { title: "打球", complete: false },
                { title: "理发", complete: false },
            ],
        };
    },
    components: {
        Header,
        Footer,
        List,
    },
    methods: {
        addTodo(todo){
            this.todos.unshift(todo)
        },
        deleteTodo(index){
            this.todos.splice(index,1)
        }
    }
};
</script>
<style>
.todo-container {
    width: 600px;
    margin: 0 auto;
}
.todo-container .todo-wrap {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
}
</style>

在这里插入图片描述

2.4 Footer组件功能

实现全选功能以及清楚已选得任务
Footer.vue

<!--  -->
<template>
    <div class="todo-footer">
        <label>
          <input type="checkbox" v-model="allCheck"/>
        </label>
        <span>
          <span>已完成{{completeNum}}</span> / 全部{{todos.length}} 
        </span>
        <button class="btn btn-danger" v-show="completeNum" @click="deleteCompleteTodos   ">清除已完成任务</button>
    </div>
</template>

<script>

export default {
  props: {
    todos:Array,
    deleteCompleteTodos:Function,
    selectAll:Function
  },
  computed: {
    completeNum()
    { 
      //这部分的函数有疑问
      return this.todos.reduce((preTotal,todo)=>preTotal+(todo.complete?1:0),0)
    },
    allCheck:{
      get(){
          return this.completeNum==this.todos.length&&this.completeNum>0
      },set(value){
            this.selectAll(value)
      }
    }
  }
}
</script>

<style>
.todo-footer {
    height: 40px;
    line-height: 40px;
    padding-left: 6px;
    margin-top: 5px;
  }
  
  .todo-footer label {
    display: inline-block;
    margin-right: 20px;
    cursor: pointer;
  }
  
  .todo-footer label input {
    position: relative;
    top: -1px;
    vertical-align: middle;
    margin-right: 5px;
  }
  
  .todo-footer button {
    float: right;
    margin-top: 5px;
  }
  
</style>

App.vue

<!--  -->
<template>
    <div id="root">
        <div class="todo-container">
            <div class="todo-wrap">
                <Header :addTodo="addTodo"/>
            
                <List :todos="todos" :deleteTodo="deleteTodo"/>
                <Footer :todos="todos" :deleteCompleteTodos="deleteCompleteTodos" :selectAll="selectAll"/>
            </div>
        </div>
    </div>
</template>
<script>
import Header from "./components/Header.vue";
import Footer from "./components/Footer.vue";
import List from "./components/List.vue";
export default {
    data() {
        return {
            todos: [
                { title: "写英语", complete: false },
                { title: "读语文", complete: false },
                { title: "打球", complete: false },
                { title: "理发", complete: false },
            ],
        };
    },
    components: {
        Header,
        Footer,
        List,
    },
    methods: {
        addTodo(todo){
            this.todos.unshift(todo)
        },
        deleteTodo(index){
            this.todos.splice(index,1)
        },
        deleteCompleteTodos (){
               this.todos=this.todos.filter(todo=>!todo.complete) 
        },
        selectAll(check){
            this.todos.forEach(todo=>(todo.complete=check))
        }
    }
};
</script>
<style>
.todo-container {
    width: 600px;
    margin: 0 auto;
}
.todo-container .todo-wrap {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值