vue框架之组件通信及插槽简介等相关内容-113

1 定义局部组件

2 组件编写方式与Vue实例的区别

1 自定义组件需要有一个root element,一般包裹在一个div中,跟vue实例一样
2 父子组件的data是无法共享
3 组件可以有data,methods,computed....,但是data 必须是一个函数
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>
<div id="box">
   <navbar></navbar>
  {{aa}}
</div>

</body>
<script>
   Vue.component('navbar', {
       template: `
       <div>
           <button @click="handleClick">返回</button>
           我是NavBar{{aa}}
           <button style="background: red">主页</button>
           <br>
           <child></child>
       </div>
   `,
       methods: {
           handleClick() {
               console.log('nav nav')
          },
      },
       components: {
           child: {
               template: `<button>儿子</button>`,
          }
      },
       data() {
           return {
               aa: 'lqz'
          }
      },
  })
   var vm = new Vue({
       el: '#box',
       data: {
           isShow: true,
      },
       methods: {
           handleClick() {
               console.log('根组件我被点击了')
          }
      },
  })

</script>
</html>

3 组件通信之父传子通信

1 父子通信
2 在全局组件上自定义属性
<navbar myname="lqz" age="18"></navbar>
3 在组件中获取
props: ['myname','age']  #myname=lqz   age=18
       
4 区分开这两种赋值方式
    <navbar myname="lqz" age="18"></navbar>
    <navbar :myname="'ffff'" age="19"></navbar>
    <navbar :myname="name" age="19"></navbar>
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>
<div id="box">
   <!--myname是自定义属性-->
   <navbar myname="lqz" age="18"></navbar>
   <navbar :myname="'ffff'" age="19"></navbar>
</div>
</body>
<script>
   Vue.component('navbar', {
       template: `
       <div>
           <button @click="handleClick">返回</button>
           我是NavBar---{{age}}
           <button style="background: red">{{myname}}</button>
       </div>
   `,
       props: ['myname','age']
  })

   var vm = new Vue({
       el: '#box',
       data: {
           name: 'xxx',
      },
  })

</script>
</html>

 

属性验证

1 限制父传子的变量类型
 props: {
           myname:String,
           isshow:Boolean
      }
2 父传子时注意以下的区别
   <navbar myname="lqz" :isshow="isshow"></navbar>
   <navbar myname="lqz" :isshow="false"></navbar>

 

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>

<div id="box">
   <!--myname是自定义属性-->
<!--   <navbar myname="lqz" isshow="false"></navbar>-->
   <navbar myname="lqz" :isshow="isshow"></navbar>
   <navbar myname="lqz" :isshow="false"></navbar>

</div>


</body>
<script>
   Vue.component('navbar', {
       template: `
       <div>
           <button>返回</button>
           我是NavBar---{{isshow}}
           <button style="background: red">{{myname}}</button>
       </div>
   `,
       props: {
           myname:String,
           isshow:Boolean
      }
  })

   var vm = new Vue({
       el: '#box',
       data: {
           name: 'xxx',
           isshow:true,
      },
  })

</script>
</html>

4 组件通信之子父通信

1 通过事件实现:
点击一下子组件,就会触发父组件某个函数的执行
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>

<div id="box">
<navbar @myevent="handleClick"></navbar>
</div>
</body>
<script>
   Vue.component('navbar', {
       template: `
       <div>
           <button @click="handleNav">点我,触发父组件的某个函数执行</button>
       </div>
   `,
       data(){
           return {
               name:'lqz'
          }
      },
       methods:{
           handleNav(){
               console.log('我是nav的函数,我执行了')
               this.$emit('myevent',100,this.name,99)
          }
      }
  })
   var vm = new Vue({
       el: '#box',
       data: {
      },
       methods:{
           handleClick(ev,a,b){
               console.log('我是父组件的函数,我执行了')
               console.log(ev)
               console.log(a)
               console.log(b)
          }
      }


  })


</script>
</html>

小案例

子组件有一个按钮,有一个输入框,当输入完内容,点击按钮,数据在父组件中展示

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>

<div id="box">
   <child @myevent="handle"></child>
   <hr>
  {{name}}
</div>

</body>
<script>
   Vue.component('child', {
       template: `
       <div>
       <input type="text" v-model="mytext">
       <button @click="handleClick">点我</button>
       </div>
   `,
       data() {
           return {
               mytext: ''
          }
      },
       methods: {
           handleClick() {
               this.$emit('myevent', this.mytext)
          }
      }
  })
   var vm = new Vue({
       el: '#box',
       data: {
           name: ''
      },
       methods: {
           handle(a) {
               this.name = a
          }
      }
  })
</script>
</html>

5 ref属性(也可实现组件间通信,子父,父子都可以使用)

ref放在标签上,拿到的是原生节点
ref放在组件上,拿到的是组件对象,
通过这种方式实现子传父(this.$refs.mychild.text)
通过这种方式实现父传子(调用子组件方法传参数)

使用

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>

<div id="box">
   <input type="text" ref="myref">

   <child ref="mychild"></child>
   <hr>
   <button @click="handleButton">点我</button>
</div>

</body>
<script>
   Vue.component('child', {
       template: `
       <div>
       <input type="text" v-model="mytext">
       <hr>
       我是子组件的input
       </div>
   `,
       data() {
           return {
               mytext: ''
          }
      },
       methods:{
           add(a){
               console.log('我是子组件的add方法')
               console.log(a)
               return '返回了'
          }
      }
  })

   var vm = new Vue({
       el: '#box',
       data: {
           name: 'asdf'
      },
       methods: {
           handle(a) {
               this.name = a
          },
           handleButton(){
               console.log(this.$refs.mychild.mytext)
               console.log(this.$refs.mychild.add(this.name))
          }
      }


  })


</script>
</html>

6 事件总线

 不同层级的不通组件通信
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>

<div id="box">

   <child1></child1>
   <hr>
   <child2></child2>

</div>

</body>
<script>

   //定义一个事件总线
   var bus=new Vue()


   //组件1
   Vue.component('child1', {
       template: `
       <div>
       <input type="text" v-model="text">
       <button @click="handleClick">点我传递数据到另一个组件</button>
       </div>
   `,
       data() {
           return {
               text: ''
          }
      },
       methods: {
           handleClick() {
               console.log(this.text)
               bus.$emit('suibian',this.text) //通过事件总线发送
          }
      }
  })
   //组件2
   Vue.component('child2', {
       template: `
       <div>
       收到的消息是:{{recv_text}}
       </div>
   `,
       data(){
           return {
               recv_text:''
          }
      },
       mounted(){//组件挂载(生命周期钩子函数中的一个),开始监听事件总线上的随便
           bus.$on('suibian',(item)=>{
               console.log('收到了',item)
               this.recv_text=item
          })

      },
  })

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

  })


</script>
</html>

7 动态组件

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>

<div id="box">

   <ul>
       <li @click="who='child1'">首页</li>
       <li @click="who='child2'">商品</li>
       <li @click="who='child3'">订单</li>
   </ul>
   <!--<component :is="who"></component>-->
   <keep-alive>
       <component :is="who"></component>
   </keep-alive>
</div>

</body>
<script>

   var vm = new Vue({
       el: '#box',
       data: {
           who: 'child1'
      },
       components: {
           child1: {
               template: `
               <div>我是首页
               <input type="text">
               </div>
               `,
          },
           child2: {
               template: `
               <div>我是商品 </div>
               `,
          },
           child3: {
               template: `
               <div>我是订单 </div>
               `,
          }
      }
  })
</script>
</html>

8 slot插槽

8.1 基本使用

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>

<div id="box">
   <child1>
       <ul>
           <li v-for="i in 4">{{i}}</li>
       </ul>
   </child1>
   <hr>
   <child2></child2>
   <hr>
   <child3></child3>
</div>

</body>
<script>

   var vm = new Vue({
       el: '#box',
       data: {
           who: 'child1'
      },
       components: {
           child1: {
               template: `

               <div>


               <slot></slot>
               <hr>
               我是首页

               <input type="text">

               </div>
               `,

          },
           child2: {
               template: `
               <div>我是商品 </div>
               `,

          },
           child3: {
               template: `
               <div>我是订单 </div>
               `,

          }
      }

  })


</script>
</html>

 

8.2 插槽案例(一个组件通过插槽控制另一个组件的显示隐藏)

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>

<div id="box">
   <child1>
       <button @click="isShow=!isShow">点我隐藏child2</button>
   </child1>
   <hr>
   <child2 v-if="isShow"></child2>
</div>

</body>
<script>

   var vm = new Vue({
       el: '#box',
       data: {
           isShow: true,
      },
       components: {
           child1: {
               template: `

               <div>
               <slot></slot>
               </div>
               `,

          },
           child2: {
               template: `
               <div>
                <ul>
                <li v-for="i in 4">{{i}}</li>
               </ul>
                </div>
               `,

          },
    }

  })


</script>
</html>

 

8.3 具名插槽(指定标签放到组件的某个插槽中)

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <script src="js/vue.js"></script>
   <title>Title</title>
</head>
<body>

<div id="box">
   <child1>
       <button @click="isShow=!isShow" slot="button1">点我隐藏child2</button>

       <div slot="div1">我是div</div>
   </child1>
   <hr>
   <child2 v-if="isShow"></child2>
</div>

</body>
<script>

   var vm = new Vue({
       el: '#box',
       data: {
           isShow: true,
      },
       components: {
           child1: {
               template: `

               <div>
               <slot name="button1"></slot>
               <hr>
               我是华丽的分割线
               <hr>
               <slot name="div1"></slot>
               </div>
               `,

          },
           child2: {
               template: `
               <div>
                <ul>
                <li v-for="i in 4">{{i}}</li>
               </ul>
                </div>
               `,

          },
    }

  })


</script>
</html>

 

原文地址:https://www.cnblogs.com/usherwang/p/14151645.html