component 组件 computed计算属性(2018/11/20)

一、 computed  计算属性
    在模板中放入太多的逻辑会让模板过重且难以维护, 所以,对于任何复杂逻辑,包括运算、函数调用等,你都应当使用计算属性。
     计算属性还有两个很实用的小技巧容易被忽略:一是计算属性可以依赖其他计算属性;  二是计算属性不仅可以依赖当前Vue 实例的数据,还可以依赖其他实例的数据
<div id="app1"></div>
<div id="app2">{{ reverseText}}</div>
<script>
var app1 = new Vue({
   el: '#app1',
data: {
      text: 'haahaha'
    }
});
 
var app2 = new Vue({
    el: '#app2',
    computed: {
        reverseText: function(){
            return app1.text.split('').reverse().join('');  //使用app1的数据进行计算        }
    }
});
</script>
 
 
    
 
二 v-bind:class   绑定class
     在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串( 不建议这样使用,因为string值是固定不变的,无法实现动态改变class的需求)之外,还可以是对象或数组。
              对象的形式:  {"类名":"关系表达式",...}
                 数组的形式:   ["类名",......]
     写在指令中的值会被视作表达式,如javascript表达式,因此v-bind:class接受三目运算
HTML代码:
<div :class="classA ? 'class-a' : 'class-b' ">Demo3</div>
 
渲染后的HTML:
<div class="class-a">Demo3</div>
 
      v-bind:class 支持对象,对象改变时会动态更新class
HTML代码:
<div :class="{ 'class-a': isA, 'class-b': isB}">Demo4</div>
 
Javascript代码:
data: {
  isA: false,  //当isA改变时,将更新class
  isB: true    //当isB改变时,将更新class
}
渲染后的HTML:
<div class="class-b">Demo4</div>
 
     v-bind:class支持数组, 数组里的变量改变时,会动态更新class列表, 数组中可以包含object类型,数组中的object对象改变,也会更新class列表
HTML代码:
<div :class="[classA, classB]">Demo7</div>
 
Javascript代码:
data: {
  classA: 'class-a',
  objectClass: {
    classB: 'class-b',  // classB 的值为class-b, 则将classB的值添加到class列表
    classC: false,    // classC值为false,将不添加classC
    classD: true    // classD 值为true,classC将被直接添加到class列表
}
}
 
渲染后的HTML:
<div class="class-a class-b classD">Demo7</div>
 
 
list.html   (  eg:v-bind:class &&  computed:{} )
 
<script src="js/vue.js"></script>
       <style type="text/css">
           .red{
               color:red
           }
           .blue{
               color:blue
           }
           .green{
               color:green
           }
       </style>
    </head>
    <body>
       <div id="box">
           <ul>
               <li v-for="(item,index) in  filterList"  v-bind:key='index'>
                  <input type='checkbox'  v-model='item.flag'>
                  {{item.text}}
               </li>
           </ul>
       <button v-on:click="type='all'">全部</button>
       <button  v-on:click="type='complete'">完成的</button>
       <button  v-on:click="type='uncomplete'">未完成的</button>
       <input type="text" v-model="n"  />{{n}}
       <p  v-bind:class="[n<60?'red':'',n>85?'blue':'',n>=60 && n<=85?'green':''  ]">{{jg}}</p><!--绑定style中的class选择符,red,blue,green都是类名-->  //数组的方法
       <!--<p  v-bind:class="{'red':n<60,'green':n>85,'blue':n>=60 && n<=85}"> {{jg}}</p>-->//对象的方法
       </div>
       <script type="text/javascript">
           var vm =new Vue({
               el:'#box',
               computed:{//计算属性    
                  jg(){
                      if(this.n<60){
                          return '不及格'
                      }
                      else if(this.n>=85){
                          return '优秀'
                      }else{
                          return "及格"
                      }
                  
               },
                  filterList(){
                      return  this.todos.filter((item)=>{
                          if(this.type==='all'){
                              return true
                          }
                          else  if(this.type==='complete'){
                              return  item.flag
                          }else{
                              return  !item.flag
                          }
                      })
                   }
                  },
               data:{
                  
                  todos:[
                    {text:'zzz',flag:true},
                     {text:'xxx',flag:false},
                    {text:'ddd',flag:true}
                  ],
                  n:'',
                  type:'all'
               }
           })
       </script>
    </body>
 
三 :component 组件 定义和使用  
         组件是可复用的 Vue 实例,且带有一个名字
      
        可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用
 
        bootstrap 引入组件  先搜索 bootcdn  ---> 找到bootstrap对应的css样式引入到文档 ---->搜索bootstrap  ---->中文文档--->components------>找到需要的组件  
      
        子组件不能更改父组件传过来的值 因为数据是单向的
 
        格式:
        1.定义一个组件名  'one'
        2.利用data 数据属性:写函数;
            ps: 数据属性data 必须是一个有返回值的函数
         
        3.template 模板:写组件的内容(元素和触发的事件)
        4.在创建的Vue根实例中将这个组件作为自定义元素来使用
 
全局组件
        Vue.component("组件的名字",{
                            template:"模板的内容"
          })
 
局部组件
        var 组件的名字 = {
                           template:"模板的内容"
            }
 
在实例中注册组件
          components:{
  
          }
子组件接收父组件传过来的值
         props:{ //对象的形式
                             v:{
                                          type:Number,    //数据类型
                                          required:true   //指定这个值必须要传,不传就报错
                                          default:50      //默认值  在  父组件没有传值的情况改下就用默认值
                        }
        }
         props:[ ]//数组的形式
生命周期函数  
          created(){       //生命周期的钩子函数,实例被创建之后自动执行代码:
            }
全局组件
       <div id="box1"><!--这里div 元素(box)就是vue实例的根元素。box就是组件元素one的父元素,要把新建的vue实例绑定在这个父元素中-->
           <one></one><!--组件中的模板可以复用,one 就是新建的组件,也就是自定义的元素-->  
           <one></one>
       </div>
<script type="text/javascript">
           //全局的组件
           Vue.component('one',{ //1.组件名为"one"; 2.data 写函数; 3.template 写组件的内容(元素和触发的事件)
               data:function(){//function可以省略不写,数据属性data 必须是一个返回值的函数
                      return {
                          msg:'hahaha'
                      }
                  },
               template:'<div>a  component{{msg}}</div>'
        //template 是模板的意思,在 html 里面是一个可以同时控制多个子元素的父元素。在这里定义了组件的内容
           })
           new Vue({
               el:'#box1' //需要管理当前div才可以显示出全局组件中的内容
           })
</script>
 
局部组件
        //局部组件
       <div id="box2">
           <my-com><my-com>
       </div>
<script>
    var myCom={
       template:"<div> the component  {{msg}}</div>",
       data(){//向模板中传值
           return{
               msg:'hello',
               tet:'ssss'
           }
       }
    }
    new Vue({
       el:'#box2',
       components:{//调用组件  注册
           myCom:myCom//如果键值名不同 用键名
       }
    })
<script>
 
四: 父组件向子组件传值(进度条例子)
 
progress.html   (父组件向子组件传值)
<link  href="https://cdn.bootcss.com/twitter-bootstrap/4.1.3/css/bootstrap.css"  rel="stylesheet"> //引入的bootstrap样式
       <script src="js/vue.js"></script>
       <style type="text/css">
           .progress{
               margin: 10px;
           }
       </style>
    </head>
    <body>
       <div id="box">
           <my-progress  v-bind:v='30'></my-progress> <!--父元素通过v向子元素传值-->
           <my-progress  v-bind:v='60'></my-progress>
           <my-progress  v-bind:v='90'></my-progress>
       </div>
       
       <script type="text/javascript">
           var  myProgress={
           props:['v'],/*子元素接受值*/
       template:`<div class="progress">
  <div class="progress-bar"  role="progressbar" v-bind:#AD0000" >v+'%'}">{{v}}%</div>
               </div>`,
       }
           new Vue({
               el:'#box',
               components:{
                  myProgress:myProgress
               }
           })
       </script>
       
    </body>
 
 
 
 
五 : 子组件向父组件
myprogress.html
 
<script src="js/vue.js"></script>
       <link  href="https://cdn.bootcss.com/twitter-bootstrap/4.1.3/css/bootstrap.css"  rel="stylesheet">
       <style type="text/css">
           .progress{
               margin:10px;
           }
       </style>
    </head>
    <body>
       <div id="box">
           <my-progress v-bind:v='30'  name='one'   v-on:child='re'  ></my-progress><!--父组件  父组件只是引入了模板中的元素 并不是标签-->
           <my-progress v-bind:v='40'  name='two'    v-on:child='re'></my-progress><!--v-bind:v传给子组件的是一个数值,如果直接v=“30”那么传的是一个字符串-->
           <my-progress v-bind:v='70'  name='three'  v-on:child='re'></my-progress><!--child是事件名   re是事件处理函数-->
           <my-progress v-bind:v='90'  name='four'   v-on:child='re'></my-progress><!--子组件给父组件传值监听-->
           {{msg}}
       </div>
       
       <script type="text/javascript">
           var  myProgress={    //子组件中的操作
           /*  props:{     //以对象的形式将父组件的值传给子组件
                  v:{
                      type:Number,    //数据类型
                      required:true   //指定这个值必须要传,不传就报错
                      default:50      //默认值  在  父组件没有传值的情况改下就用默认值
                  }
               },*/
               props:['v','name'],//数组的形式传值 不能有别的限定单纯把v中的值传给子组件 ,name也是父组件中定义的值
              created(){ //生命周期的钩子函数,实例被创建之后执行代码
                  var timer =  setInterval(()=>{
                      this.n++;
                      if(this.n===100){
                          clearInterval(timer);
                          this.$emit('child',this.name);//子组件给父组件传值发送    进度条加载完成后把值发送给父组件   $emit('事件名','数据')是发送  
                      }
                  },300)
                  
               },
               data(){
                  return{
                      n:this.v
                  }
               },
               
               template:`<div  class="progress">   //子组件
                           <div  class="progress-bar" :  >{{n}}%</div>
                    </div>`
           }
           
           new Vue({    //父组件中的操作
               el:'#box',
               data:{   //将子组件传过来的值接收在这个msg中 渲染到页面上
                  msg:''
               },
               components:{
                  myProgress
               },
               methods:{    //在父组件的methods里写事件处理的函数,参数是子组件传给父组件的值
                  re(v){    //接收  子组件给父组件传值过来的值
                      this.msg='任务'+v+'已完成';
                  }
               }
           })
       </script>
    </body>
 
六、兄弟组件之间的传值  (将兄弟组件之间的传值转化为父子组件的传值   son1-->father   father---->son2)
add del1.html(子组件给父组件传值-----添加操作)  
 
    <link  href="https://cdn.bootcss.com/twitter-bootstrap/4.1.3/css/bootstrap.css"  rel="stylesheet">
       <script src="js/vue.js"></script>
    </head>
    <body>
       <div id="box">
           <txt v-on:add='addItem'></txt> //监听到add的时候父元素触发一个addItem函数
       </div>
       <script type="text/javascript">
           var txt ={
               template:`<div><input  type='text' v-model='txt'  v-on:keyup.enter='add'></div>`,//子组件通过add方法把input框中的值发送给父元素
               data(){
                  return{
                      txt:''//定义txt数据
                  }
               },
               methods:{
                  add(){
                      this.$emit('add',this.txt) //发送txt的内容
                      this.txt=''
                  }
               }
           }
           var vm = new Vue({
               el:'#box',
               components:{
                  txt
               },
               data:{
                  todoList:[]
               },
               methods:{
                  addItem(content){ //将获取到的内容填入todos
                      this.todoList.push(content)
                  }
               }
           })
       </script>
    </body>
 
 
add.del(父组件将从son1处获取到的数据 传给son2-----删除操作)
                   son1将添加的数据传给父组件,
                父组件通过addItem方法将数据添加进todoList,
                son2拿到todoList中的所有数据 当点击删除按钮的时候触发del事件, 
                父组件监听到子组件发送的index 调用removeItem方法 删除父组件中对应的数据。
 
<body>
       <div id="box">
           <txt v-on:add='addItem'></txt>
           <list v-bind:todolist='todolist'  v-on:dell='removeItem'></list>//绑定todoList,从中获取数据
       </div>
       
       <script type="text/javascript">
           var txt={
               template:`<div><input  type='text'  v-model='txt'  @keyup.enter='add' ></div>`,
               data(){
                  return{
                      txt:''
                  }
               },
               methods:{
                  add(){
                      this.$emit('add',this.txt)
                      this.txt=''
                  }
               }
           }
           
           var list = {
               props:['todolist'],//子组件接收父组件传过来的值
               template:`<div>
                          <ul>
                              <li  v-for='(item,index) in todolist'>{{item}}
                              <button   v-on:click='del'>删除</button> //这里的del是一个方法
                              </li>
                          </ul>
                        </div>`,
           methods:{
               del(){
                   this.$emit('dell',this.index)//这里的dell是事件名,并且同时发送下标信息
               }
           }
           }
       
           var vm=new Vue({
               el:'#box',
               components:{
                  txt:txt,
                  list:list
               },
               data:{
                  todolist:['aa']
               },
               methods:{
                  addItem(content){
                      this.todolist.push(content);
                  },
                  removeItem(index){    //()中的内容就是父组件接收到的信息
                      this.todolist.splice(index,1)
                  }
               }
           })
       </script>
    </body>
 
 
七、动态组件
 
<component v-bind:is="组件名对应的变量名"></component>  //动态组件
<keep-alive>   // 可以缓存
 
dynamic.html(选项卡效果)
 
<body>
       <div id="box">
           <button   v-on:click="cname='one'">a</button>
           <button  v-on:click="cname='two'">b</button>
           <keep-alive> <!--缓存组件中的内容-->
           <component  v-bind:is='cname'></component><!--cname是变量名-->
           </keep-alive>
       </div>
       
       <script type="text/javascript">
           var  one = { 
               template:`<div>aaaa
                  <input type='text' > //缓存后即使点了别的选项再次点回这个选项时input框中的内容也依然在
              </div>`
           }
           
           var two = { 
               template:`<div>bbbb</div>`
           }
           
           var vm = new Vue({
               el:'#box',
               data:{
                  cname:'one' //默认是one中的内容 如果不写就不显示任何内容   cname是变量名  one是组件名
               },
               components:{
                  one,two
               }
           })
       </script>
    </body>
 
 
封装一个tab选项卡
 
<body>
       <div id="box">
           <tab :title="['a','b','c']"    :content="['aaaa','bbbb','cccc']"></tab>
       </div>
       
       <script type="text/javascript">
           var tab = {
               props:['title','content'],
               created(){
                   this.arr=this.content.map((item)=>{// 用map方法将content中的每个元素转为组件
                      return{
                          template:`<div>${item}</div>`
                          //template中定义的就是子组件    ES6中的变量要保存在${}中
                      }
                  })
               },
               template:`<div>
               <ul>
                  <li v-for='(item,idx) in  title' v-on:click="index=idx" >{{item}}</li>
               </ul>
               <component   v-bind:is="arr[index]"></component>
               //arr[index]代表的是组件
               
               </div>`,
               data(){
                  return{
                      arr:[],//存放的组件,每个元素都是组件
                      index:0
                  }
               }
           }
           
           var vm = new Vue({
               el:'#box',
               components:{
                  tab
               }
           })
       </script>
    </body>
posted @ 2019-09-12 10:28  zsrTaki  阅读(321)  评论(0编辑  收藏  举报