Vue.js - 组件

一、全局组件注册

用data属性

  • data必须是一个函数
  • 组件的模板内容必须是一个单个的根元素
  • 组件模板内容可以是模板字符串
  • 注意事项:在字符串模板中,用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件

eg:添加点击增加2

    <script type="text/javascript">
      window.onload = function () {
        Vue.component('buttonCounter',{可以用驼峰命名法
          data: function () {
            return{
              count: 0,
            }
          },
          template:`
            <button @click="count++">
              点击了{{count}}次
            </button>`,
        })
        const vm = new Vue({
          el:'#app',
        })
      }
    </script>
</head>
<body>
    <div id="app">
      <button-counter></button-counter>  在标签模板中不能使用驼峰命名法
      <button-counter></button-counter>
    </div>
</body>

二、局部组件注册

component属性

    <script type="text/javascript">
      window.onload = function () {
        var HelloWorld = {
          data:function () {
            return {
              msg:'HelloWorld'
            }
          },
          template: '<div>{{msg}}</div>'
        };
        var HelloTom = {
          data:function () {
            return {
              msg:'HelloTom'
            }
          },
          template: '<div>{{msg}}</div>'
        };
        const vm = new Vue({
          el:'#app',
          data:{

          },
          components:{
            'hello-world':HelloWorld,
            'hello-tom':HelloTom,
          }
        });
      }
    </script>
</head>
<body>
    <div id="app">
      <hello-world></hello-world>
      <hello-tom></hello-tom>
    </div>
</body>

三、组件间的数据交互

3.1父组件向子组件传值

  • 组件内部通过props接受传递过来的值
  • 父组件中通过属性将值传递给子组件
 <script type="text/javascript">
      window.onload = function () {
        Vue.component('menu-item',{
          props:['title']    子组件通过props接受
          data:function () {
            return {
              msg:'子组件本身的数据'
            }
          },
          template:'<div>{{msg + "------" + title}}</div>'
        });
        const vm = new Vue({
          el:'#app',
          data:{
            pmsg:'父组件中的内容'
          },
        })
      }
    </script>
</head>
<body>
    <div id="app">
      <div>{{pmsg}}</div>         父组件通过title属性值来传值
      <menu-item title = '来自父组件的值'></menu-item>  
    </div>
</body>
  • 通过v-bind具体的绑定一个属性值
  <script type="text/javascript">
    window.onload = function () {
      Vue.component('menu-item',{
        props:['title','content'],//子组件通过props接受
        data:function () {
          return {
            msg:'子组件本身的数据'
          }
        },
        template:'<div>{{msg + "------" + title + content}}</div>'
      });
      const vm = new Vue({
        el:'#app',
        data:{
          pmsg:'父组件中的内容',
          ptitle:'动态绑定属性'
        },
      })
    }
  </script>
</head>
<body>
<div id="app">
  <div>{{pmsg}}</div>
  <menu-item :title = 'ptitle' content = 'hello'></menu-item>
</div>
</body>

在这里插入图片描述

3.2props的属性名规则

  • 在props中使用驼峰形式,html模板中使用短横线方式
  • 字符串形式的模板中没有这个限制
    在这里插入图片描述
  • 显示原始数值的算术,则用v-bind的方式
  <script type="text/javascript">
    window.onload = function () {
      Vue.component('menu-item',{
        props:['title'],//子组件通过props接受
        data:function () {
          return {
            msg:'子组件本身的数据'
          }
        },
        template:'<div>{{title + 12}}</div>'
      });
      const vm = new Vue({
        el:'#app',
        data:{
          ptitle:'动态绑定属性'
        },
      })
    }
  </script>
</head>
<body>
<div id="app">
  <menu-item title = '12'></menu-item>  不用v-bind的形式,显示的是字符串
  <menu-item :title = '12'></menu-item>  用v-bind的方式现实的是数值
</div>
</body>

显示结果:
在这里插入图片描述

  • props传递数据的原则:单向数据流
    只允许父组件传递数值到子组件

3.3:子组件向父组件传值

  • 子组件通过自定义事件向父组件传递信息

  • 父组件监听子组件的事件

类比于现实中的实例:比如儿子给父亲打钱。儿子对应子组件,父亲对应父组件,请按顺序看。

    <script type="text/javascript">
      window.onload = function () {
        Vue.component("child",{
          data(){
            return {
              childname:"子组件状态"
            }
          },
          template:`
            <div>
              child组件
              <button @click="payMoney">click</button> 3:儿子收到卡号后的行为是执行打钱行动,payMoney()函数,转4:
            </div>
          `,
          methods:{
            payMoney(){   4:转钱的卡号是myevent,数额是1000.(此处的1000就是个参数),this.$emit是查询卡号的必要步骤  转5this.$emit("myevent",1000)
            }
          }
        });
        const vm = new Vue({
          el:'#app',
          data:{

          },
          methods:{
            handleEvent(ev) {  2:银行卡的作用:收到传来的钱后再控制台中显示收到钱了console.log();3:
              console.log("父组件收到钱了",ev);
            }
          }
        })
      }
    </script>
</head>
<body>
    <div id="app">//父组件,child为子组件
      父组件
      <child @myevent = "handleEvent($event)"></child>  1:父亲先给儿子(child组件)提供一张银行卡,这张银行卡的号叫myevent,事件用@来监听,这张银行卡的作用是handleEvent()函数。转2</div>  5:父亲的银行卡需要接受1000(接受子组件中的参数),固定方式是$event
</body>

结果显示:
在这里插入图片描述

四、组件refs通信

  • ref 放在标签上,拿到的是原生节点
  • ref 放在组件上,拿到的是组件对象
    <script type="text/javascript">
      window.onload = function () {
        Vue.component("child",{
          template:`
            <div>
              child
            </div>
          `,
          data(){
            return {
              childName:"子组件的状态"
            }
          }
        })
        const vm = new Vue({
          el:'#app',
          data:{

          },
          methods:{
            handle(){
              console.log(this.$refs);  this.$refs会获取父组件中ref指向,即两个dom节点,一个子节点没有mychild,一个父节点mytext
             // console.log(this.$refs.mychild);  获取的是子节点
            }
          }
        })
      }
    </script>
</head>
<body>
    <div id="app">
      <input type="text" ref = "mytext"> 
      <child ref = "mychild"></child>
      <button @click="handle">点击</button>
    </div>
</body>

在这里插入图片描述

五、组件非父子通信(兄弟通信)

事件总线mounted

  • mounted,生命周期进行监听,在当前组件dom创建完就会调用
  • 创建一个空的父组件vue实例bus
  • 用bus. o n 来 监 听 , 用 b u s . on来监听,用bus. onbus.emit来发送
    <script type="text/javascript">
      window.onload = function () {
        var bus = new Vue();//中央事件总线
        Vue.component("weixinauthor",{
          template:`<div>
              <input type="text" ref = "mytext">
              <button @click="handclick">发布</button>
           </div>`,
          methods:{
            handclick(){
              bus.$emit("weixinmessage",this.$refs.mytext.value);
            }
          }
        })
        Vue.component("weixinuser",{
          //用bus.$on订阅
          template:`<div style="background-color: yellow">
            我是一个微信用户
          </div>`,
          mounted(){//在当前组件dom创建完就会调用
            bus.$on("weixinmessage",(data)=>{
              console.log("收到推送",data)
            })
          }
        })
        const vm = new Vue({
          el:'#app',
          data:{

          },
        })
      }
    </script>
</head>
<body>
    <div id="app">
      <weixinauthor></weixinauthor>
      <weixinuser></weixinuser>
    </div>
</body>

六、动态组件

  • < compontent>元素,动态地绑定多个组件到它的is属性
  • < keep-alive> 保留状态,避免重新渲染
    <script type="text/javascript">
      window.onload = function () {
        const vm = new Vue({
          el:'#app',
          data:{
            who:'home'
          },
          methods:{

          },
          components:{
            "home":{
              template:`<div><input type="text">home</div>`
            },
            "list":{
              template:`<div>list</div>`
            },
            "shopcar":{
              template:`<div>shopcar</div>`
            }
          }
        })
      }
    </script>
</head>
<body>
    <div id="app">
      <keep-alive>
        <component :is = "who"></component>
      </keep-alive>

      <footer>
        <ul>
          <li @click="who = 'home'"><a href="#">首页</a></li>
          <li @click="who = 'list'"><a href="#">列页表</a></li>
          <li @click="who = 'shopcar'"><a href="#">购物车页面</a></li>
        </ul>
      </footer>
    </div>
</body>

显示结果:
在这里插入图片描述

  • 来回切换后,input中的内容不变

七、组件的插槽slot

  • slot:插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。
    <script type="text/javascript">
      window.onload = function () {
        Vue.component("child",{
          template:`<div>
            <slot></slot>
            child
          </div>`
        })
        const vm = new Vue({
          el:'#app',
          data:{

          },
        })
      }
    </script>
</head>
<body>
    <div id="app">
      <child><div>aaaaaaaaaa</div></child>
    </div>
</body>

结果显示:
在这里插入图片描述

具名slot:可以将组将插到指定的位置

  • 用slot来命名
  • 用name来声明
  <script type="text/javascript">
    window.onload = function () {
      Vue.component("child",{
        template:`<div>
            <slot name = "a"></slot>
            child
            <slot name = "b"></slot>
          </div>`
      })
      const vm = new Vue({
        el:'#app',
        data:{

        },
      })
    }
  </script>
</head>
<body>
<div id="app">
  <child>
    <div slot="a">aaaaaaaaaa</div>
    <div slot="b">bbbbbbbbbb</div>
  </child>
</div>
</body>

结果显示:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值