vue学习笔记之组件化开发二(父子组件的访问(children、refs、parent)、slot插槽)

一、父子组件的访问方式
父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问跟组件。
父组件访问子组件:使用 c h i l d r e n 或 children或 childrenrefs
子组件访问父组件:使用 p a r e n t 我 们 先 来 看 下 parent 我们先来看下 parentchildren的访问
this.$children是一个数组类型,它包含所有子组件对象。
一、如代码父组件访问子组件的值与调用子组件的方法

<div id="app">
	  <cpn></cpn>   //这里开了两个子组件标签
	  <cpn></cpn>
	
	  <button @click="btnClick">按钮</button>
	</div>
	
	<template id="cpn">
	  <div>我是子组件</div>
	</template>
	<script src="../js/vue.js"></script>
	<script>
	  const app = new Vue({
	    el: '#app',
	    data: {
	      message: '你好啊'
	    },
	    methods: {
	      btnClick() {
	         console.log(this.$children);            //再点击的时候访问子组件,this.$children,访问到是两个子组件数组,数组里面装的是子组件
	         for (let c of this.$children) {        //遍历这个数组
	           console.log(c.name);        //访问它的值
	           c.showMessage();          //调用它的方法
	        } 
	         console.log(this.$children[1].name);  //访问第二个子组件的值
	      }
	    },
	    components: {
	      cpn: {
	        template: '#cpn',
	        data() {
	          return {
	            name: '我是子组件的name'        //子组件的值
	          }
	        },
	        methods: {
	          showMessage() {              //子组件的方法
	            console.log('showMessage');
	          }
	        }
	      },
	    }
	  })
	</script>

c h i l d r e n 的 缺 陷 : 通 过 children的缺陷: 通过 childrenchildren访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。
但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化(比如再数组中间插一个值,使数组序列号发生变化)。
二、 r e f s 的 使 用 : 有 时 候 , 我 们 想 明 确 获 取 其 中 一 个 特 定 的 组 件 , 这 个 时 候 就 可 以 使 用 refs的使用: 有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用 refs使使refs
r e f s 和 r e f 指 令 通 常 是 一 起 使 用 的 。 首 先 , 我 们 通 过 r e f 给 某 一 个 子 组 件 绑 定 一 个 特 定 的 I D 。 其 次 , 通 过 t h i s . refs和ref指令通常是一起使用的。 首先,我们通过ref给某一个子组件绑定一个特定的ID。 其次,通过this. refsref使refIDthis.refs.ID就可以访问到该组件了。


	<div id="app">
  <cpn></cpn>
  <cpn></cpn>
  <cpn ref="aaa"></cpn>                   //这里使用ref 属性给这个子组件定义个标识符
  <button @click="btnClick">按钮</button>
</div>

<template id="cpn">
  <div>我是子组件</div>
</template>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    },
    methods: {
      btnClick() {
        // 2.$refs => 对象类型, 默认是一个空的对象 ref='bbb'
        console.log(this.$refs.aaa.name);       //再使用的时候,通过this.$refs.标识符.属性,就可以获取这个属性的值,
      }
    },
    components: {
      cpn: {
        template: '#cpn',
        data() {
          return {
            name: '我是子组件的name'
          }
        },
        methods: {
          showMessage() {
            console.log('showMessage');
          }
        }
      },
    }
  })
</script>

三、父子组件的访问方式: p a r e n t 如 果 我 们 想 在 子 组 件 中 直 接 访 问 父 组 件 , 可 以 通 过 parent 如果我们想在子组件中直接访问父组件,可以通过 parent访parent
注意事项:
尽管在Vue开发中,我们允许通过 p a r e n t 来 访 问 父 组 件 , 但 是 在 真 实 开 发 中 尽 量 不 要 这 样 做 。 子 组 件 应 该 尽 量 避 免 直 接 访 问 父 组 件 的 数 据 , 因 为 这 样 耦 合 度 太 高 了 。 如 果 我 们 将 子 组 件 放 在 另 外 一 个 组 件 之 内 , 很 可 能 该 父 组 件 没 有 对 应 的 属 性 , 往 往 会 引 起 问 题 。 另 外 , 更 不 好 做 的 是 通 过 parent来访问父组件,但是在真实开发中尽量不要这样做。 子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。 如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。 另外,更不好做的是通过 parent访访parent直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于我的调试和维护。

<div id="app">
  <cpn></cpn>
</div>

<template id="cpn">
  <div>
    <h2>我是cpn组件</h2>
    <ccpn></ccpn>
  </div>
</template>

<template id="ccpn">
  <div>
    <h2>我是子组件</h2>
    <button @click="btnClick">按钮</button>
  </div>
</template>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    },
    components: {
      cpn: {
        template: '#cpn',
        data() {
          return {
            name: '我是cpn组件的name'
          }
        },
        components: {
          ccpn: {
            template: '#ccpn',
            methods: {
              btnClick() {
                // 1.访问父组件$parent
                // console.log(this.$parent);
                // console.log(this.$parent.name);  

                // 2.访问根组件$root   
                console.log(this.$root);   //根组件是vue ,  而其他父组件是vuecomponent
                console.log(this.$root.message);
              }
            }
          }
        }
      }
    }
  })

二、组件化高级开发
一、slot插槽
插槽的意思与作用:在生活中很多地方都有插槽,电脑的USB插槽,插板当中的电源插槽。
插槽的目的是让我们原来的设备具备更多的扩展性。
比如电脑的USB我们可以插入U盘、硬盘、手机、音响、键盘、鼠标等等。
组件的插槽:
组件的插槽也是为了让我们封装的组件更加具有扩展性。
让使用者可以决定组件内部的一些内容到底展示什么。
栗子:移动网站中的导航栏。
移动开发中,几乎每个页面都有导航栏。
导航栏我们必然会封装成一个插件,比如nav-bar组件。
一旦有了这个组件,我们就可以在多个页面中复用了。
最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽。
一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。
是搜索框,还是文字,还是菜单。由调用者自己来决定。

二、slot基本使用

1.插槽的基本使用
2.插槽的默认值 button
3.如果有多个值, 同时放入到组件进行替换时, 一起作为替换元素

1、基本使用,再使用组件的时候,为呈现每个组件不同的样子,而现在插槽的功能就出现了,如果模板那里没有 的时候, 里面里面放的标签是不会显示的

<div id="app">  
			  <cpn><span>哈哈哈</span></cpn>      //2、这里面的标签才能实现
			  <cpn><i>呵呵呵</i></cpn>
			  <cpn></cpn>
			</div>
			<template id="cpn">
			  <div>
			    <h2>我是组件</h2>
			    <p>我是组件, 哈哈哈</p>
			    <slot></slot>  //1、这里使用了插槽                            
			  </div>
			</template>
			
			<script src="../js/vue.js"></script>
			<script>
			  const app = new Vue({
			    el: '#app',
			    data: {
			      message: '你好啊'
			    },
			    components: {
			      cpn: {
			        template: '#cpn'
			      }
			    }
			  })
			</script>

2、如果组件cpn标签里没有如标签内容的时候,就会把里面的内容去变成cpn标签里面的内容,

<!DOCTYPE html>
		<html lang="en">
		<head>
		  <meta charset="UTF-8">
		  <title>Title</title>
		</head>
		<body>
		
		<div id="app">
		  <cpn></cpn>
		
		  <cpn><span>哈哈哈</span></cpn>
		  <cpn><i>呵呵呵</i></cpn>
		  <cpn>                             //这是再组件内设置多组值
		    <i>呵呵呵</i>
		    <div>我是div元素</div>
		    <p>我是p元素</p>
		  </cpn>
		  <cpn></cpn>
		  <cpn></cpn>
		</div>
		
		
		<template id="cpn">
		  <div>
		    <h2>我是组件</h2>
		    <p>我是组件, 哈哈哈</p>
		    <slot><button>按钮</button></slot>         //这里设置了,如果组件标签内没有值,那么插槽内的值就会就会是组件内的值,如果有值,就呈现值
		  </div>
		</template>
		
		<script src="../js/vue.js"></script>
		<script>
		  const app = new Vue({
		    el: '#app',
		    data: {
		      message: '你好啊'
		    },
		    components: {
		      cpn: {
		        template: '#cpn'
		      }
		    }
		  })
		</script>
		
		</body>
		</html>

vue学习笔记之组件化开发二(父子组件的访问(children、refs、parent)、slot插槽)_第1张图片
3、多个插槽的情况
如代码,此时有三个插槽,由结果图片可以看到,由于只有一个cpn组件,所以这三个插槽的内容就像一个插槽里的三个内容一样,都会传给cpn里面

<div id="app">
		  <cpn></cpn>
		</div>
		<template id="cpn">
		  <div>
		    <slot ><span>左边</span></slot> 
		    <slot ><span>中间</span></slot>
		    <slot ><span>右边</span></slot>
		  </div>
		</template>

在这里插入图片描述
那多个插槽多个cpn呢
如代码,由结果可以看到,每一个cpn都能得到所有的插槽

	<div id="app">
  <cpn></cpn>
  <cpn></cpn>
  <cpn></cpn>
</div>
<template id="cpn">
  <div>
    <slot ><span>左边</span></slot>
    <slot ><span>中间</span></slot>
    <slot ><span>右边</span></slot>
  </div>
</template>

vue学习笔记之组件化开发二(父子组件的访问(children、refs、parent)、slot插槽)_第2张图片

4、具名插槽的使用
当子组件的功能复杂时,子组件的插槽可能并非是一个。
比如我们封装一个导航栏的子组件,可能就需要三个插槽,分别代表左边、中间、右边。
那么,外面在给插槽插入内容时,如何区分插入的是哪一个呢?
这个时候,我们就需要给插槽起一个名字
如何使用具名插槽呢?
给slot元素一个name属性即可
然后通过name去控制具体的某个插槽的显示
比较复杂,我们一步步来研究
首先看代码,结果是替换cpn里面的内容没有替换一个插槽,原因是它的span标签带有对应具名插槽得到slot属性

	<div id="app">
  <cpn><span slot="aaa">标题</span></cpn>
</div>
<template id="cpn">
  <div>
    <slot ><span>左边</span></slot>
    <slot ><span>中间</span></slot>
    <slot ><span>右边</span></slot>
  </div>
</template>

在这里插入图片描述
再看代码,这时候,带有name属性的并且值对应的插槽被对应的cpn替换了,其他插槽五影响,只替换有对应属性的

	<div id="app">
  <cpn><span slot="aaa">标题</span></cpn>
</div>
<template id="cpn">
  <div>
    <slot name="aaa"><span >左边</span></slot>
    <slot ><span>中间</span></slot>
    <slot ><span>右边</span></slot>
  </div>
</template>

在这里插入图片描述
编译作用域
这是个什么东西呢,看代码,下面就是验证父组件的作用域和子组件的作用域再哪,然后说明父组件的作用域不能直接用子组件里面的属性,子组件同理,所以下面代码的cpn是能够显示东西的

	<div id="app">  //这个app是父组件的东西,属于父组件作用域
  <cpn v-show="isShow"></cpn> //v-show决定是否显示
</div>
<template id="cpn">
  <div>
    <h2>我是子组件</h2>
    <p>我是内容, 哈哈哈</p>
    <button v-show="isShow">按钮</button>
  </div>
</template>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      isShow: true     //父组件定义一个ture值的 isShow
    },
    components: {
      cpn: {
        template: '#cpn',
        data() {
          return {
            isShow: false  //子组件定义一个false值的 isShow
          }
        }
      },
    }
  })

作用域插槽的使用
如代码

<div id="app">
			  <cpn>
			    <template slot-scope="slot">  //2、调用那些存储起来的数据需要用到template和slot-scope属性,就可以调用了
			      <span>{{slot.data.join(' - ')}}</span> //3、这样子调用
			    </template>
			  </cpn>
			  <!--<cpn></cpn>-->
			</div>
			<template id="cpn">
			  <div>
			    <slot :data="pLanguages">   //1、再子组件的模板的插槽里,用来把子组件的数据存储起来,data是自定义的
			    </slot>
			  </div>
			</template>
			<script src="../js/vue.js"></script>
			<script>
			  const app = new Vue({
			    el: '#app',
			    data: {
			      message: '你好啊'
			    },
			    components: {
			      cpn: {
			        template: '#cpn',
			        data() {
			          return {
			            pLanguages: ['JavaScript', 'C++', 'Java', 'C#', 'Python', 'Go', 'Swift']
			          }
			        }
			      }
			    }
			  })

上面这个案例用一句话概括,父组件替换插槽的标签,但是内容由子组件来提供。

你可能感兴趣的:(vue)