vue-基础5——组件

组件的注册

https://cn.vuejs.org/v2/guide/components-registration.html

<body>

  <div id="box">
      <navbar></navbar>
  </div>


  <script type="text/javascript">
        // vue 组件 :扩展html元素
        //组件是一个孤岛,无法(直接)访问到外部的 data,methods.......
        //将来可以通过通信方式来进行沟通
        //全局组件定义方式
      

        Vue.component("navbar",{
          template:`
            <div>
              <nav style="background:yellow;">
                <button @click="handleClick()">返回</button>
                <navbarchild1></navbarchild1>          //全局注册的子组件
                <navbarchild2></navbarchild2>          //局部注册的子组件
                <ul>
                    <li>11111</li>
                    <li>22222</li>
                </ul>
                {{myname}}
              </nav>
              <div>最外层必须有root element</div>
            </div>
          `,
          components:{
            //局部定义组件
            navbarchild2:{
              // data(){}
              watch: {},
              template:`<div style="background:blue;">我是局部定义的,其他人休想得到我</div>`
            }
          },
          methods: {
            handleClick(){
              console.log("返回功能")
            }
          },
          //组件中 data必须是一个方法, return 返回对象
          //保证data不会相互影响
          data(){
            return {
              myname:"我是导航栏",
            }
          }
        })
        //全局定义的
        Vue.component("navbarchild1",{
          template:`
            <div style="background:red;">
                1.不要吐槽此时的组件,我虽然没有高亮,虽然没有代码提示,
                但是这个时间,能用上我,也是一种好的选择
                2.样式这个时候只能先写行内样式
                3.之后单文件组件 都会解决这些问题。  
            </div>
          `
        })
        new Vue({
          el:"#box",
          methods: {
            
          },
          watch: {
            
          },
          computed: {
            
          },
        })

  </script>
</body>
组件编写方式与Vue实例的区别
            *自定义组件需要有一个root element
            *父子组件的data是无法共享
            *组件可以有data,methods,computed....,但是data 必须是一个函数
 

组件通信

(1)父传子

父传子的方式非常简单,在父组件上绑定一个属性,在子组件上用props接受就可以了

<body>
   <div id="box">
      <!-- 首页中引入的 -->
      <navbar mytitle="home" :myshow="false" :mytext="text"></navbar>
      <!-- 列表页面引入的 -->
      <navbar mytitle="list" :myshow="true" :mytext="text"></navbar>
      <!-- 购物车页面引入的 -->
      <navbar mytitle="shopcar" :myshow="true" :mytext="text"></navbar>
   </div>
   <script>
     //home
      Vue.component("navbar",{
        template:`
          <nav>
            <button v-if="myshow">返回</button>
            <span>我是导航--{{mytitle}}-{{mytext}}</span>  
            <button v-show="myshow">主页</button>  
          </nav>
        `,
        //接受父组件传来的属性 mytitle myshow
        // props:["mytitle","myshow"]
        //属性验证
        props :{
          mytext:String,
          mytitle:String,
          myshow:Boolean //接受的myshow必须是boolean类型 Array Number
        }
      })
      // root compoennt
      new Vue({
        el:"#box",
        data:{
          text:"我是在父组件中定义"
        }
      })
   </script> 
</body>

(2)子传父

子串父的实现方式是在父子身上绑定一个函数,在触发子组件身上的函数时,调起父组件的函数并为其传数据

<body>
    <div id="box">
      <my-child  @kerwinevent1="handleEvent1" @kerwinevent2="handleEvent2"></my-child>
      <!-- <myChild></myChild> -->
    </div>
       
    <script>
      Vue.component("myChild",{
        template:`
          <div>
            child-<button @click="handleClick()">click</button>
          </div>
        `,
        data(){
          return {
            text:"child定义的状态"
          }
        },
        methods: {
          handleClick(){
            //把text状态传到父组件中
            //触发,分发
            this.$emit("kerwinevent2",100000)
            this.$emit("kerwinevent1",this.text)
          }
        },
      })

      //root component
       new Vue({
         el:"#box",
         data:{

         },
         methods:{
          handleEvent1(data){
            console.log("收到钱了-11111",data)
          },
          handleEvent2(data){
            console.log("收到钱了-22222",data)
          }
         }
       })
    </script>

</body>

(3)ref

ref放在标签上, 拿到的是原生节点
ref放在组件上, 拿到的是组件对象,通信功能
<body>
    <div id="box">
      <input type="text" ref="mytext"/>
      <button @click="handleClick()">click</button>

      <child ref="mychild"></child>
    </div>
   
    <script type="text/javascript">

        Vue.component("child",{
          data(){
            return {
              childtext:"child定义的"
            }
          },
          template:`<div>
              child  -{{childtext}}
          </div>`
        })

        //子组件
        new Vue({
          el:"#box",
          methods: {
            handleClick(){
              console.log(this.$refs.mychild.childtext)
              this.$refs.mychild.childtext= "22222222222"
            }
          },
        })
    </script>
</body>

(4)中央事件总线-bus

<body>
    <div id="box">
      <child1></child1>
      <child2></child2>
    </div>
   
    <script type="text/javascript">
        //中央事件总线    
      var bus = new Vue() //中央事件总线 bus.$on  bus.$emit

      Vue.component("child1",{
        template:`
          <div>
            child1-<button @click="handleClick()">click</button>
          </div>
        `,
        methods: {
          handleClick(){
            //
            bus.$emit("kerwinevent","来自child1的问候")
            console.log("emit触发bus事件")
          }
        },
      }) 
      Vue.component("child2",{
        template:`
          <div>
            child2  
          </div>
        `,
        mounted() {
          console.log("自动被调用, 等child上树就会被执行 立即监听事件")

          bus.$on("kerwinevent",(data)=>{
            console.log("child2函数被执行",data)
          })
        },
        
      }) 
    
      var vm = new Vue({
          el:"#box",
          methods: {
           
          },
        })
    </script>
</body>

  

动态组件

https://cn.vuejs.org/v2/guide/components.html#%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6

<body>
    <div id="box">
      <keep-alive>
        <component :is="type"></component>
      </keep-alive>
      <footer>
        <ul>
          <li @click="type='home'">首页</li>
          <li @click="type='list'">列表</li>
          <li @click="type='shopcar'">购物车</li>
        </ul>
      </footer>
    </div>
   

    <script type="text/javascript">

        Vue.component("home",{
          template:`<div>
            home -<input type="text"/>
          </div>`
        })
        Vue.component("list",{
          template:`<div>
            list  
          </div>`
        })
        Vue.component("shopcar",{
          template:`<div>
            shopcar  
          </div>`
        })

        new Vue({
          el:"#box",
          data:{
            type:"home"
          }
        })
    </script>
</body>

  

原文地址:https://www.cnblogs.com/wuziqiang/p/13280197.html