Vue-组件

发布于 2020-02-28  174 次阅读


组件

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<style>
  .navbar{
    background: red;
  }
</style>
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
   
    <div id="box">
      <navbar></navbar>
      
      <sidebar></sidebar>

      <navbar></navbar>

      <!-- <app-child></app-child> -->
    </div>

   
    <script type="text/javascript">
          //1. 全局定义组件 (作用域隔离)
          
          Vue.component("app-child",{
            template: `
              <div>child</div>
            `
          })


          Vue.component("navbar",{
            template: `<nav style="background:red">
              <button @click="handleClick()">返回-{{text}}</button>
              <span>导航栏</span>
              <app-child></app-child>
              <navbarchild></navbarchild>
            </nav>`,

            data(){
              return {
                text:"111111"
              }
              // 组件与组件 的状态需要相互隔离, 要设计成函数。
            },

            methods:{
              handleClick(){
                console.log("click--navbar");
                this.text="222222";
              }
            },
            components:{
              navbarchild:{
                template:`<div>navbarchild--{{title}}</div>`,
                data(){
                  return {
                    title:"111111111"
                  }
                }
              }
            }
          })

          Vue.component("sidebar",{
            template: `<div style="background:blue">
              <ul @click="handleClick">
                <li>1111</li>
                <li>2222</li>
                <li>3333</li>
              </ul>
              <app-child></app-child>
              <navbarchild></navbarchild>
            </div>`,
            methods:{
              handleClick(){
                console.log("click--sidebar");
              }
            }
          })
          

          var vm = new Vue({
            el:"#box"
          }) //根组件(root )
    </script>
</body>


</html>

 

组件父传子

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<style>
  .navbar{
    background: red;
  }
</style>
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
   
    <div id="box">
      {{title}}
      <!-- <img :src="title"/> -->
      <navbar myword="home" :myshow="false"></navbar>
      <navbar myword="list" :myshow="true"></navbar>
      <navbar myword="shopcar" :myshow="true"></navbar>
      <navbar :myword="title" :myshow="true"></navbar>
      <!-- <app-child></app-child> -->
    </div>

   
    <script type="text/javascript">
          //1. 全局定义组件 (作用域隔离)
          


          Vue.component("navbar",{
            template: `<nav style="background:red">
              <button @click="handleClick()" v-show="myshow">返回-{{text}}</button>
              <span>导航栏--{{myword}}---{{myshow}}</span>
            </nav>`,

            //接受父组件传来的属性
            // props:["myword","myshow"],

            //属性验证
            props:{
              myword:String,
              myshow:Boolean
            },

            data(){
              return {
                text:"111111"
              }
              // 组件与组件 的状态需要相互隔离, 要设计成函数。
            },

            methods:{
              handleClick(){
                console.log("click--navbar");
                this.text="222222";
              }
            }
          })

       

          var vm = new Vue({
            el:"#box",
            data:{
              title:"根组件中定义的title"
            }
          }) //根组件(root )
    </script>
</body>


</html>

 

组件子传父

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">

<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
    <div id="box">
      <child @myevent="handleMyEvent($event)"></child>
    </div>
   

    <script type="text/javascript">
        //子组件
        Vue.component("child",{
          template:`<div>
            child-<button @click="handleClick">send</button>
          </div>`,

          data(){
            return {
              money:1000000
            }
          },
          methods:{
            handleClick(){
              console.log("把消息传给父组件")
              this.$emit("myevent",this.money);// emit 分发
            }
          }
        })
       
        var vm = new Vue({
          el:"#box",
          data:{

          },

          methods:{
            handleMyEvent(data){
              console.log("我收到了钱",data)
            }
          }
        })
      

    </script>
</body>
</html>

 

组件-卖座

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">

<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
    <div id="box">
        <navbar @myevent="control"></navbar>
        <sidebar v-show="isShow"></sidebar>
    </div>
   
   

    <script type="text/javascript">
        //子组件
       Vue.component("navbar",{
        template:`<div>

          navbar--<button @click="handleClick">show/hide</button>
        </div>`,

        methods:{
          handleClick(){
            this.$emit("myevent");
          }
        }
       })


       Vue.component("sidebar",{
        template:`<div>

          sidebar
          <ul>
            <li>1111</li>
            <li>1111</li>
            <li>1111</li>
            <li>1111</li>
            <li>1111</li>
            <li>1111</li>
            <li>1111</li>
          </ul>
        </div>`
       })

       
        var vm = new Vue({
          el:"#box",
          data:{
            isShow:false
          },
          methods:{
            control(){
              this.isShow = !this.isShow;
            }
          }
        })
      

    </script>
</body>
</html>

 

组件-refs

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">

<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
    <div id="box">
      <button @click="handleClick()">get</button>
      <child ref="mychild"></child>


      <input type="text" ref="mytext"/>
      <button @click="handleAdd">add</button>

    </div>
   

    <script type="text/javascript">
        //子组件
      
        Vue.component("child",{
          template:`<div>
              child 子组件
             
          </div>`,

          data(){
            return {
              childname:"11111111111111111111"
            }
          },

          methods:{
            handleClick(data){
              console.log("child-11111",data)
            }
          }
        })

        var vm = new Vue({
          el:"#box",
          data:{

          },
          methods:{
            handleClick(){
              console.log(this.$refs.mychild.childname); //获取引用
            
              this.$refs.mychild.handleClick("给你5管麻药");//调用的子组件的方法
            },

            handleAdd(){
              console.log("handleAdd",this.$refs.mytext.value)
            }
          }
        })
      

    </script>
</body>
</html>

 

组件非父子通信

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">

<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
    <div id="box">
       
        <child1></child1>
        <child2></child2>
       
    </div>
   

    <script type="text/javascript">
      // eventEmitter  .on  .emit
      var bus = new Vue()// 空vue实例 中央事件总线  

      Vue.component("child1",{
        template:`<div>
          child1---<button @click="handleClick">通信</button>
        </div>`,
        methods:{
          handleClick(){
            // 向自己兄弟child1 发送一句
            // setInterval(() => {
            //   bus.$emit("kerwin","兄弟,这是麻药");
            // }, 1000)
             bus.$emit("kerwin");
          }
        },
        mounted(){
          console.log("这个函数会在child1组件创建成功后自动被vue调用")
        }
      })  



       Vue.component("child2",{
        template:`<div>
          child2--一直显示

          <ul v-show="isShow">
            <li>111111</li>
          </ul>
        </div>`,
        data(){
          return {
            isShow:true
          }
        },

        mounted(){
          console.log("这个函数会在child2组件创建成功后自动被vue调用")

          bus.$on("kerwin",(data)=>{
            // console.log(data);
            this.isShow = !this.isShow
          })
        }
      })  
     
      new Vue({
        el:"#box",
        // template:"<div>hello template</div>"
      })
   
    </script>
</body>
</html>

 

动态组件

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<style type="text/css">
  
    *{
      margin: 0px;
      padding: 0px;
    }

    html,body{
      width: 100%;
      height: 100%;
    }
   footer ul {
    display: flex;
    position: fixed;
    left: 0px;
    bottom: 0px;
    width: 100%;
    height: 40px;
   }

   footer ul li {
    flex: 1;
    text-align: center;
    list-style: none;
    height: 40px;
    line-height: 40px;
    background: gray;
   }


   .bounce-enter-active {
     animation: bounce-in .5s;
   }
   .bounce-leave-active {
     animation: bounce-in .5s reverse;
   }
   @keyframes bounce-in {
     0% {
       transform: translateX(100px);
       opacity: 0;
     }
     
     100% {
       transform: translateX(0px);
       opacity: 1;
     }
   }
</style>
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
    <div id="box">
       <keep-alive>
         <component :is="who"></component>
       </keep-alive>
       <footer>
         <ul>
           <li><a @click="who='home'">首页</a></li>
           <li><a @click="who='list'" >列表页</a></li>
           <li><a @click="who='shopcar'">购物车页面</a></li>
         </ul>
       </footer>
    </div>
   

    <script type="text/javascript">
      //babel-loader  ES6=>ES5
    

      var home= {
        template:`<div>
          home
          <input type="text"/>
        </div>`
      }

      var list= {
        template:`<div>
          list
        </div>`
      }

      var shopcar= {
        template:`<div>
          shopcar
        </div>`
      }


    	var vm = new Vue({
        el:"#box",
        data:{
            // isHomeShow:true,
            // isListShow:false,
            // isShopcarShow:false
            who:"home"
        },
        components:{
          home, 
          list,
          shopcar
        }
      })

    </script>
</body>
</html>

 

总结

1. 组件编写方式与Vue实例的区别
      *自定义组件需要有一个root element
      *父子组件的data是无法共享
      *组件可以有data,methods,computed....,但是data 必须是一个函数
2. 组件通信
      i. 父子组件传值 (props down, events up)
      ii. 属性验证
            props:{name:Number}
            Number,String,Boolean,Array,Object,Function,null(不限制类型)
      iii. 事件机制
            a.使用 $on(eventName) 监听事件
            b.使用 $emit(eventName) 触发事件
      iv. Ref
            <input ref="mytext"/> this.$refs.mytext
      v. 事件总线
            var bus = new Vue();
      * mounted生命周期中进行监听
3. 动态组件
      *<component> 元素,动态地绑定多个组件到它的 is 属性
      *<keep-alive> 保留状态,避免重新渲染

 


注错之当