vue slot 02-scope slot $parent, $children, recursive component


Tip: The following is the content of this article, the following cases are for reference

4. Scope slot

Official website: Sometimes it is useful to allow slot content to access data that is only available in subcomponents.

The overall architecture refers to the vue slot 01 in the previous article.
Sometimes you want to change the backup content. For example, the content of the Wrap component template is as follows:

App.vue
	<Wrap> 
	//这里为空时填充备用内容
	// {
    
    {value}} 这里是获取不到Wrap组件中的value
    </Wrap>
Wrap.vue
	<h1>wrap</h1>
    <slot> 
     这是slot标签内容备用内容{
    
    {
    
    value}}
    </slot>
    <p>这是wrap的P标签</p>
    <hr />

In order to make value available in the parent's slot content, we can bind value as an attribute of the element :

Note: v-slot can only be added to the template, and only those that receive the value in it can write directly like this

App.vue
	<h1>wrap</h1>
	//注意v-slot只能添加在template上,只有在里面接收值的可以这样直接写
	<Wrap v-slot:default="wrapValue">  
      {
    
    {
    
    wrapValue}}
      <Box :title="wrapValue.data"/> //Box组件也可以获取到这个值
    </Wrap>
Wrap.vue 	
	    <h1>wrap</h1>
	    <slot :data="value"> //进行绑定
	     这是slot标签内容备用内容{
    
    {
    
    value}}
	    </slot>
	    <hr />
    <script>
		export default {
    
    
		  data() {
    
    
		    return {
    
    
		      value: "wrap-value",
		    }
		  },
		};
	</script>
Box.vue	  
	   <h2>Box</h2> {
    
    {
    
    title}}
	<script>
	export default {
    
    
	  props: {
    
    
	    title: String,
	  }
	};
	</script>

Insert picture description here
Deconstruct the slot:

	<Wrap v-slot:default="{data}"> 
      {
    
    {
    
    data}}
      <Box :title="data"/>
    </Wrap>

Insert picture description here

  1. The v-slot without parameters is assumed to correspond to the default slot:
  2. Note that the abbreviated syntax of the default slot cannot be mixed with the named slot, because it will cause the scope to be ambiguous
  3. As long as there are multiple slots, always use the complete template-based syntax for all slots.
    Example:
//Wrap.vue
	<template>
	  <div class="wrap">
	    <h1>wrap</h1>
	    <slot :data="value"> 
	     这是slot标签内容备用内容{
    
    {
    
    value}}
	    </slot>
	    <slot name="list" :data="list" />
	    <hr />
	  </div>
	</template>
	<script>
	export default {
    
    
	  data() {
    
    
	    return {
    
    
	      value: "wrap-value",
	      list:[1,2,3,4]
	    };
	  },
	};
</script>
//App.vue
	<template>
	  <div id="app">
	    app
	    <Wrap>
	      <template v-slot:defalut="{ data }">
	        <Box :title="data" />
	      </template>
	      <template v-slot:list="{ data }">
	        <ul>
	          <li v-for="(item, index) in data" :key="index">
	            {
    
    {
    
     item }}
	          </li>
	        </ul>
	      </template>
	    </Wrap>
	  </div>
	</template>
	<script>
	import Wrap from "./components/Wrap";
	import Box from "./components/Box";
	export default {
    
    
	  components: {
    
    
	    Wrap,
	    Box,
	  }
	};
	</script>

run:
Insert picture description here

5.$parent, $children

  1. $parent gets the parent component instance (you can use this.$parent directly in the child component)
  2. $children gets the child component instance (you can use this.$children directly in the parent component)
  3. You can also get the data in the component and modify the data
//App.vue
<template>
  <div id="app">
    app
    <Wrap ref="wrap">
      <Box />
      <h1>test</h1>
      <Foo />
    </Wrap>
  </div>
</template>
<script>
import Wrap from "./components/Wrap";
import Box from "./components/Box";
import Foo from './components/Foo'
export default {
    
    
  components: {
    
    
    Wrap,
    Box,
    Foo
  }
};
</script>

Wrap.vue

<template>
  <div class="wrap" :style="{ background: bgColor }">
    <h1>wrap value: {
    
    {
    
     value }}</h1>
    <slot />
  </div>
</template>
<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      value: "hello",
      bgColor: "green",
    };
  },
  methods: {
    
    
    setBgColor() {
    
    
      this.bgColor = "#ddd";
    },
  },
  mounted() {
    
    
    console.log(this.$children);
  },
};
</script>

<style>
.wrap {
    
    
  padding: 40px;
  background: red;
}
</style>

Box.vue

<template>
  <div class="box">
    <h2>box</h2>
    <button @click="modifyAction">按钮</button>
  </div>
</template>
<script>
export default {
    
    
  mounted(){
    
    
    console.log(this.$parent);
  },
  methods: {
    
    
    modifyAction(){
    
    
      console.log(this.$parent.value) //获取父组件的数据
      console.log(this.$parent.bgColor)
      this.$parent.value = 'hi!'
      console.log(this.$parent.value)
      this.$parent.setBgColor();
      console.log(this.$parent.bgColor);

    }
  }
}
</script>
<style>
.box{
    
    
  background: yellow;
}
</style>

The code is as follows (example):
Insert picture description here
Click
Insert picture description here
Insert picture description here

6. Recursive components

View app

<template>
  <div id="app">
    app
    <demo :value="5" />
  </div>
</template>
<script>
import Demo from "./components/Demo";

export default {
    
    
  components: {
    
    
    [Demo.name]: Demo,
  },
};
</script>

Demo.vue
can call the component itself in the template inside the component only after the name of the component is set here

<template>
  <div class="demo" :style="{background:`rgb(${r},${g},${b})`}">
      <button v-if="value>1" @click="showAction">按钮</button>
      <demo v-if="isShow && value>1"  :value="value-1" />
  </div>
</template>

<script>
export default {
    
    
    //只有在这里设置了组件的名字后,才能在组件内部的template中调用组件自身    
    name:'demo',
    props:{
    
    
        value:Number,
    },
    data(){
    
    
        return{
    
    
            r:Math.random()*255,
            g:Math.random()*255,
            b:Math.random()*255,
            isShow:false,
        }
    },
    methods:{
    
    
        showAction(){
    
    
            this.isShow=!this.isShow;
        }
    }
}
</script>

<style>
.demo{
    
    
  padding: 20px;
  border: 1px solid #ddd;
}
</style>

Running effect chart:
Insert picture description here


Guess you like

Origin blog.csdn.net/qq_46057900/article/details/109393404