深入了解Vue插槽

2020年12月30日11:03:09 发表评论 42 次浏览

本文概述

很多时候, 我们可能希望将数据从一个组件传递到另一个组件-不是采用传统的父子组件方法, 而是采用使组件可重用的方法。

组件用于制作Web模板, 你可以将其放到不同的地方以重新呈现相同类型的代码。如果你可以重用组件, 但根据估算的属性在不同的位置以不同的方式呈现该组件, 将会有多酷?很酷

使用Vue插槽, 你可以将部分或全部组件转换为可重复使用的模板, 这些模板将根据不同的用例进行不同的呈现。你需要做的就是将它们嵌入插槽。

在本文中, 我将帮助你了解Vue插槽的概念, 并向你展示如何使用它们。

插槽的基本用法

因此, 我们从插槽的定义中了解了整个概念-这是关于使组件可重用。现在, 我们将通过一些示例展示Vue广告位, 并讨论如何使用它们。

我们将在其中创建一些按钮应用程序并允许按钮重复使用Buttons.vue:

/**App.vue**/
<template>
  <div id="app">
  <button-helper>
    <button type="button" class="Red">Red</button>
    <button type="button" class="Green">Green</button>
    <button type="button" class="Blue">Blue</button>
  </button-helper>
  </div>
</template>
<script>
import buttonHelper from './components/Buttons.vue'
export default {
  name: 'App', components: {
    'button-helper':buttonHelper
  }
    }
</script>

<style>
.Red{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:red;
  text-align: center;
  cursor:pointer;
}
.Green{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:Green;
  text-align: center;
  cursor:pointer;
}
.Blue{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:blue;
  text-align: center;
  cursor:pointer;
}
</style>
//Buttons.vue

<template>
<div>
  <slot></slot>
  </div>
</template>
<script>
export default {
  name: 'Buttons', }
</script>
三个按钮的列表:一个红色,一个绿色和一个蓝色。

在上面的示例中, 我们在我们的按钮中创建了一些按钮<App> </ App>模板。我们也将他们召唤到我们的Buttons.vue。当我们删除<slot> </ slot>从应用程序, 我们只会看到<h1>按钮列表</ h1>显示。

这是因为你不能从一个组件传递组件的属性(应用程序)到另一个组件(Buttons.vue), 只需将属性嵌入子组件标签中即可。

我们为制作了一个自定义演示.
不完全是。点击这里查看.

深入了解Vue插槽1

如果我们想控制按钮的呈现方式怎么办Buttons.vue?我们可能希望先渲染一个绿色按钮, 然后再渲染一个红色按钮。

下面的示例说明了如何通过以不同方式呈现组件来重用组件:

//App.vue

<template>
  <div id="app">
  <button-helper>
    <h1 slot="title">List of Buttons</h1>
    <button slot="red" type="button" class="Red">Red</button>
    <button slot="green" type="button" class="Green">Green</button>
    <button slot="blue" type="button" class="Blue">Blue</button>
  </button-helper>
  </div>
</template>
<script>
import buttonHelper from './components/Buttons.vue'
export default {
  name: 'App', components: {
    'button-helper':buttonHelper
  }
    }
</script>

<style>
.Red{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:red;
  text-align: center;
  cursor:pointer;
}
.Green{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:Green;
  text-align: center;
  cursor:pointer;
}
.Blue{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:blue;
  text-align: center;
  cursor:pointer;
}
</style>
//Buttons.vue
<template>
<div>
  <h1>This is the list of buttons from App.vue</h1>
<div>
  <slot name="title"></slot>
  <slot name="green"></slot>
</div>
<div>
  <slot name="title"></slot>
  <slot name="blue"></slot>
</div>
<div>
  <slot name="title"></slot>
  <slot name="red"></slot>
  </div>
<div>
  <slot name="title"></slot>
  <slot name="blue"></slot>
  <slot name="red"></slot>
  <slot name="green"></slot>
</div>
</div>
</template>
<script>
export default {
  name: 'Buttons', }
</script>
我们的按钮列表现在称为插槽。

在上方, 我们已经命名了广告位。当我们要传递多个属性作为广告位时, 这非常重要-我们需要为广告位分配名称。例如, 当我们调用它们时, 我们可能不希望所有插槽一起出现。

这样, 我们可以通过调用子组件的名称来从子组件中调用所需的插槽。

我们通过添加名称来命名广告位slot =" name"我们想要传递给子组件的父组件中的属性。我们通过添加以下内容来在子组件中调用命名槽<slot name =" name"> </ slot>到我们要调用广告位的位置。此方法称为具有名称属性的命名槽。

我们也可以使用垂直槽指令<模板>。这样, 广告位的名称将作为垂直槽的论点:

//Buttons.vue
<template>
  <div>
    <h1>List of Buttons</h1>
    <slot name="green"></slot>
    <slot name="red"></slot>
    <slot name="blue"></slot>
  </div>
</template>
<script>
export default {
  name: 'Buttons', }
</script>
//App.vue
<template>
  <div id="app">
    <Buttons>
      <template v-slot:green>
        <button class="Green">I am Green</button>
      </template>
    </Buttons>
      <Buttons>
      <template v-slot:blue>
        <button class="Blue">I am Blue</button>
      </template>
    </Buttons>
      <Buttons>
      <template v-slot:red> 
        <button class="Red">I am Red</button>
      </template>
    </Buttons>
    </div>
</template>
<script>
import Buttons from './components/Buttons'
export default {
  name: 'App', components: {
    Buttons, }
    }
</script>
<style>
.Red{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:red;
  text-align: center;
  cursor:pointer;
}
.Green{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:Green;
  text-align: center;
  cursor:pointer;
}
.Blue{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:blue;
  text-align: center;
  cursor:pointer;
}
</style>

数据绑定

现在, 让我们深入研究通过绑定表达式传递广告位的一些高级方法。这样, 我们可以根据用例(特别是来自用户输入的内容)渲染插槽, 就像在操作DOM时一样。

我们将创建一个简单的程序来绑定子组件中的数据(Buttons.vue)到父组件(应用程序), 根据用户的输入:

// Button.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <slot name="propsTest" :count="count" :addOne="addOne" />
  </div>
</template>
<script>
export default {
  name: "Buttons", props: {
    msg: String
  }, data() {
    return {
      count: 0
    };
  }, methods: {
    addOne() {
      this.count++;
    }
  }
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
<template>
  <div id="app">
    <Buttons msg="Simple Slot Binding With Counter Program">
      <template v-slot:propsTest="{ count, addOne }">
        <p>{{ count }}</p>
        <button @click="addOne" class="Red">Add One</button>
      </template>
    </Buttons>
  </div>
</template>
<script>
import Buttons from "./components/Buttons";
export default {
  name: "app", components: {
    Buttons
  }
};
</script>
<style>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.Red{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:red;
  text-align: center;
  cursor:pointer;
}
</style>
一个红色的按钮,上面写着“发送”。

在上面的示例中, 我们将计数器属性从Button.vueto应用程序并通过使用添加了一个按钮老虎机.

后备内容

因此, 我们可能希望将后备内容分配给Button.vue这样, 如果没有分配属性应用程序或其他组件从中访问数据Button.vue, 该组件可以回退到回退内容:

//Buttons.vue
<template>
<button type="submit" class="Red">
  <slot>Submit</slot>
</button>
</template>
<script>
export default {
  name: 'Buttons', }
</script>
<style>
.Red{
  width:120px;
  height: 50px;
  margin: 50px;
  padding: 10px;
  background-color:red;
  text-align: center;
  cursor:pointer;
}
</style>
//App.vue
<template>
  <div id="app">
    <Buttons>
      send
    </Buttons>
  </div>
</template>

<script>
import Buttons from './components/Buttons'
export default {
  name: 'App', components: {
    Buttons, }
    }
</script>
一个红色的按钮,上面写着“发送”。

如果我们删除第5行中的发送按钮应用程序, 我们将看到按钮中的文本从提交to发送.

范围插槽

要在Vue中传递属性, 你需要在父组件中定义数据并为该数据分配一个值。然后, 将属性值传递给子组件, 以便数据成为子组件中的属性。

但是, 如果使用作用域插槽, 则需要将子组件的属性传递到作用域插槽中, 然后从父组件访问它们。这与Vue中传递的传统属性相反。此概念是为了允许父组件访问子组件上的某些数据。

为了正确理解这个概念, 我们将创建一个简单的表达式, 然后使用以下命令将属性从子组件传递到父组件中槽镜.

//App.vue
<template>
  <div>
    <Buttons>
      <template slot-scope="firstSlotScope">
        <p>{{firstSlotScope.text}}</p>
        <!-- Renders <p>I'll get rendered inside the first slot.</p> -->
      </template>
      <template slot="not-first" slot-scope="secondSlotScope">
        <p>{{secondSlotScope.text}}</p>
        <!-- Renders <p>I'll get rendered inside the second slot.</p> -->
      </template>
    </Buttons>
  </div>
</template>
<script>
import Buttons from './components/Buttons';
export default {
  name: 'App', components: {
    Buttons, }
}
</script>
//Buttons.vue
<template>
  <div>
    <h1>Scoped Slots Example</h1>
    <slot :text="firstSlotText"></slot>
    <slot name="not-first" :text="secondSlotText"></slot>
  </div>
</template>
<script>
export default {
  name: 'Buttons', data() {
    return {
      firstSlotText: "I'll get rendered inside the first slot, I'll be first to be rendered.", secondSlotText: "I'll get rendered inside the second slot, I'll be second to be rendered."
    }
  }
}
</script>
作用域插槽示例。

无需绑定数据并使用Vue插槽为其分配值, 你可以作为道具从父组件访问子组件上的数据。

总结

我们已经看到了通过使用slot属性来重用组件属性的不同方法。本文还说明了如何动态地或使用slot属性命名插槽。我们还看到了如何使用插槽将特定数据从子组件传递到父组件, 以及如何使用作用域的插槽。

你可以使用此插槽进行更多练习Github回购。 ReadMe.md文件中随附了所有建立存储库的说明。可以找到该项目的完整代码这里.

你可以阅读更多有关Vue插槽在Vue的官方网站上。随意地联系如果你对本文有任何建议或疑问, 请与我联系。

准确体验用户的Vue应用程序

调试Vue.js应用程序可能会很困难, 尤其是在用户会话中有数十种甚至数百种变体的情况下。如果你有兴趣监视和跟踪生产中所有用户的Vue突变,

尝试notlogy

.

LogRocket仪表板免费试用横幅

https://notlogy.com/signup/

日志火箭就像Web应用程序的DVR一样, 实际上记录了Vue应用程序中发生的所有事情, 包括网络请求, JavaScript错误, 性能问题等等。你可以汇总并报告问题发生时应用程序所处的状态, 而不用猜测为什么会发生问题。

notlogy Vuex插件将Vuex突变记录到notlogy控制台, 为你提供导致错误的原因以及发生问题时应用程序处于何种状态的上下文。

现代化调试Vue应用程序的方式-免费开始监控.

一盏木

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: