精华内容
下载资源
问答
  • Vue slot 详解

    千次阅读 多人点赞 2021-07-31 11:17:19
    Vue中,我们使用组件来组织页面和组织代码,类似于搭积木,每一个组件都是一个积木,使用一些相同或者不同组件就能搭建出我们想要的页面。slot(插槽)是组件功能的重要组成部分,插槽必须用于组件才有意义。它为...

    Vue中,我们使用组件来组织页面和组织代码,类似于搭积木,每一个组件都是一个积木,使用一些相同或者不同组件就能搭建出我们想要的页面。slot(插槽)是组件功能的重要组成部分,插槽必须用于组件才有意义。它为组件提供了对外的接口,允许从组件外部传递内容,并将这部分内容放置到指定的位置。

    使用 slot

    当一个组件可能被使用至少两次并且两次使用内容(这里指组件视图的组成)不同时,插槽才有存在的必要。注意: 本文的代码都是基于Vue3编写

    基础用法

    Link.vue

    <template>
      <a :href="href" class="link">
        <!-- 留个插槽,外界传入内容放置在这里 -->
        <slot></slot>
      </a>
    </template>
    
    <script>
    export default {
      props: {
        href: {
          required: true,
          type: String,
        },
      },
    };
    </script>
    
    <style lang="less" scoped>
    .link {
      display: inline-block;
      line-height: 1;
      white-space: nowrap;
      cursor: pointer;
      background: #fff;
      border: 1px solid #dcdfe6;
      color: #606266;
      -webkit-appearance: none;
      text-align: center;
      box-sizing: border-box;
      outline: none;
      margin: 0;
      transition: 0.1s;
      font-weight: 500;
      padding: 12px 20px;
      font-size: 14px;
      border-radius: 4px;
    }
    </style>
    

    App.vue

    <template>
      <div class="app">
        <Link href="https://baidu.com"> 百度</Link>
        <br />
        <Link href="https://google.com" style="margin-top: 10px">
          <!-- 这里允许放置任意的内容,包括字符串和标签 -->
          <span>Icon</span>谷歌</Link
        >
      </div>
    </template>
    
    <script>
    import Link from "./Link.vue";
    
    export default {
      components: {
        Link,
      },
    };
    </script>
    

    视觉效果:

    image.png

    以上实现了两个组件Link.vueApp.vueLink.vue是一个链接组件,在组件内部已经定义好了样式,然后链接的内容交由外界使用时填充。在App.vue组件内则使用了Link.vue组件两次,并且两次传入的内容不同。

    具名插槽

    上面的Link.vue只要求填充一份内容,那么当我们需要在组件的好几个位置都填充不同的内容应该怎么办?这时候可以使用具名插槽,就是给组件的每个填充区域都取个名字,这样在使用的时候就可以往对应名字的那个区域填充内容。

    Page.vue

    <template>
      <div class="page">
        <header class="page-header">
          <slot name="header"></slot>
        </header>
        <div class="page-center">
          <aside class="page-aside">
            <slot name="aside"></slot>
          </aside>
          <div class="page-content">
            <slot name="content"></slot>
          </div>
        </div>
        <footer class="page-footer">
          <slot name="footer"></slot>
        </footer>
      </div>
    </template>
    
    <script>
    export default {
      setup() {
        return {};
      },
    };
    </script>
    
    <style lang="less">
    body {
      margin: 0;
    }
    .page {
      border: 1px solid #333;
      width: 100vw;
      height: 100vh;
      display: flex;
      flex-direction: column;
      &-header {
        height: 50px;
        border-bottom: 1px solid #333333;
      }
      &-center {
        flex: 1;
        display: flex;
      }
      &-aside {
        width: 150px;
        border-right: 1px solid #333333;
      }
      &-content {
        flex: 1;
      }
    
      &-footer {
        border-top: 1px solid #333;
        height: 30px;
      }
    }
    </style>
    

    App.vue

    <template>
      <Page style="width: 500px; height: 300px; margin: 30px 30px">
        <template v-slot:header>这是标题</template>
        <template v-slot:aside>这是侧边栏</template>
        <template v-slot:content>这是内容区域</template>
        <template v-slot:footer>这是页脚</template>
      </Page>
    
      <Page style="width: 500px; height: 300px; margin: 30px 30px">
        <template v-slot:header>
          <h2>走过路过</h2>
        </template>
        <template v-slot:aside>
          <ul>
            <li>东临碣石</li>
            <li>以观沧海</li>
          </ul>
        </template>
        <template v-slot:content>这是内容区域</template>
        <template v-slot:footer>这是页脚</template>
      </Page>
    </template>
    
    <script>
    import Page from "./Page.vue";
    
    export default {
      components: {
        Page,
      },
    };
    </script>
    

    效果图:
    image.png

    作用域插槽

    为啥叫作用域插槽?首先要搞清楚作用域这个概念。在JS中,作用域表示的是当前的执行上下文,只有在当前作用域中变量才可以被使用。作用域有层次之分,分为父作用域和子作用域,子作用域可以访问父作用域中的变量,这一层层的往上则形成了作用域链。JS中只有全局作用域和函数作用域,ES6新增了块级作用域。关于作用域,这里不再赘言,有需要的同学可以去MDN作用域查看。

    Vue本质上还是js,模板最终会被编译成render函数,每个组件都有一个render函数。下面先看个例子:

    Count.vue

    <template>
      <div>
        <p>当前数字:{{ count }}</p>
        <button @click="onAdd">+</button>
        <button @click="onMinus">-</button>
        <slot></slot>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          count: 0,
        };
      },
      methods: {
        onAdd() {
          this.count++;
        },
        onMinus() {
          this.count--;
        },
      },
    };
    </script>
    

    App.vue

    <template>
      <div>
        <Count style="border: 1px solid red">
          <p>这就是填充Count组件的插槽</p>
          <p>appCount:{{ appCount }}</p>
          <p>Count组件中的count变量:{{ count }}</p>
        </Count>
        <br />
        <button @click="onClick">app add</button>
      </div>
    </template>
    
    <script>
    import Count from "./Count.vue";
    
    export default {
      components: {
        Count,
      },
      data() {
        return {
          appCount: 0,
        };
      },
      methods: {
        onClick() {
          this.appCount++;
        },
      },
    };
    </script>
    

    效果图:

    image.png

    从上面的效果图中可以看到,在App.vue组件中使用Count.vue组件时,在Count.vue组件的插槽中,能够访问appCount变量,但是不能访问Count.vue组件的Count变量,这是为什么呢?理论上,插槽传入的内容最终会插入到Count.vue组件中,那么也应该可以访问Count.vue组件的变量才对啊?

    父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

    上面的一段引用摘自Vue文档,这段文字表明了,在App.vue中的一切,包括Count.vue组件的插槽内容都是在App.vue组件下编译的,也就是Count.vue组件的插槽模板可以访问App.vue组件的所有变量,但不能访问Count.vue的任意变量。如果我一定要在插槽中访问Count.vue的count变量呢?这个时候作用域插槽就派上用场了。

    作用域插槽允许在组件中对插槽所在的上下文暴露某一些变量,改写以上的Count.vue组件,

    Count.vue

    <template>
      <div>
        <p>当前数字:{{ count }}</p>
        <button @click="onAdd">+</button>
        <button @click="onMinus">-</button>
        <!-- 把count变量暴露到插槽作用域 -->
        <slot :count="count"></slot>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          count: 0,
        };
      },
      methods: {
        onAdd() {
          this.count++;
        },
        onMinus() {
          this.count--;
        },
      },
    };
    </script>
    

    App.vue

    <template>
      <div>
        <Count style="border: 1px solid red">
         <!--Count组件插槽暴露的所有变量都放在 slotProps对象中 -->
          <template v-slot="slotProps">
            <p>这就是填充Count组件的插槽</p>
            <p>appCount:{{ appCount }}</p>
            <p>Count组件中的count变量:{{ slotProps.count }}</p>
          </template>
        </Count>
        <br />
        <button @click="onClick">app add</button>
      </div>
    </template>
    
    <script>
    import Count from "./Count.vue";
    
    export default {
      components: {
        Count,
      },
      data() {
        return {
          appCount: 0,
        };
      },
      methods: {
        onClick() {
          this.appCount++;
        },
      },
    };
    </script>
    

    这就是作用域插槽,本质上了是允许在父组件作用域访问到子组件作用域,它为插槽模板区域提供了一个数据来源于子组件的上下文。作用域插槽的用处还是挺广的,总的来说当你需要它时自然会用到它,如果想提前学习,可以看一下elementUI的table组件

    slot 实现

    上面就插槽的使用说了一大堆,关于插槽的实现还是没有涉及,下文讲解在Vue中插槽是如何实现的?

    首先,我们都知道,无论是使用jsx还是模板,最终都会编译成render函数,并且render函数在执行之后会输出 Virtual Dom ,下面先看一个组件在编译完成之后是什么样子?

    Comp.vue

    <template>
      <div>
       	<p>count: {{count}}</p>
        <button @click="onClick">
          ADD
        </button>
        <slot :count="count"></slot>
      </div>
    </template>
    <script>
     import {defineComponent, ref} from 'vue'
    
     export default defineComponent((props) => {
       const count = ref(0);
       const onClick = () => {
         count.value++
       }
       return {
         count,
         onClick
       }
     }) 
    </script>
    

    App.vue

    <template>
      <div>
       <Comp>
       	<template v-slot="slotProps">
          <p>
             {{magRef}}: {{slotProps.count}}
          </p>
        </template> 
       </Comp>
      </div>
    </template>
    
    <script>
       import {defineComponent, ref} from 'vue'
      import Comp from './Comp.vue'
    
      
     export default defineComponent({
       components: {Comp},
       setup(props) {
         const magRef = ref('当前的数字是')
         return {
           magRef
         }
       }
     }) 
    </script>
    

    Comp.vue编译之后:

    /* Analyzed bindings: {} */
    import {
      defineComponent,
      ref
    } from 'vue'
    
    const __sfc__ = defineComponent((props) => {
      const count = ref(0);
      const onClick = () => {
        count.value++
      }
      return {
        count,
        onClick
      }
    })
    
    import {
      toDisplayString as _toDisplayString,
      createElementVNode as _createElementVNode,
      renderSlot as _renderSlot,
      openBlock as _openBlock,
      createElementBlock as _createElementBlock
    } from "vue"
    
    function render(_ctx, _cache, $props, $setup, $data, $options) {
      return (_openBlock(), _createElementBlock("div", null, [
        _createElementVNode("p", null, "count: " + _toDisplayString(_ctx.count), 1 /* TEXT */ ),
        _createElementVNode("button", {
          onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.onClick && _ctx.onClick(...args)))
        }, " ADD "),
        _renderSlot(_ctx.$slots, "default", {
          count: _ctx.count
        })
      ]))
    }
    __sfc__.render = render
    __sfc__.__file = "Comp.vue"
    export default __sfc__
    

    App.vue编译之后:

    /* Analyzed bindings: {} */
    import {
      defineComponent,
      ref
    } from 'vue'
    import Comp from './Comp.vue'
    
    
    const __sfc__ = defineComponent({
      components: {
        Comp
      },
      setup(props) {
        const magRef = ref('当前的数字是')
        return {
          magRef
        }
      }
    })
    
    import {
      toDisplayString as _toDisplayString,
      createElementVNode as _createElementVNode,
      resolveComponent as _resolveComponent,
      withCtx as _withCtx,
      createVNode as _createVNode,
      openBlock as _openBlock,
      createElementBlock as _createElementBlock
    } from "vue"
    
    function render(_ctx, _cache, $props, $setup, $data, $options) {
      const _component_Comp = _resolveComponent("Comp")
    
      return (_openBlock(), _createElementBlock("div", null, [
        _createVNode(_component_Comp, null, {
          default: _withCtx((slotProps) => [
            _createElementVNode("p", null, _toDisplayString(_ctx.magRef) + ": " + _toDisplayString(slotProps.count), 1 /* TEXT */ )
          ]),
          _: 1 /* STABLE */
        })
      ]))
    }
    __sfc__.render = render
    __sfc__.__file = "App.vue"
    export default __sfc__
    

    这里给大家推荐一个尤雨溪搞的测试网站Vue SFC Playground 可以直接看到组件编译之后的js代码。

    image.png

    这个编译是在加载.vue文件的时候就执行了,runtime阶段是不存在模板字符串了(使用UMD的时候会存在),在浏览器中执行的都是编译之后的js。下面具体分析一下以上Comp.vueApp.vue编译之后的js代码。

    首先在Comp.vue中,<slot :count="count"></slot>会被编译成_renderSlot(_ctx.$slots, "default", {count: _ctx.count}),下面看看_renderSlot中干了什么?

    export type Slot = (...args: any[]) => VNode[]
    
    export type InternalSlots = {
      [name: string]: Slot | undefined
    }
    export function renderSlot(
      slots: Slots,
      name: string,
      props: Data = {},
      // this is not a user-facing function, so the fallback is always generated by
      // the compiler and guaranteed to be a function returning an array
      fallback?: () => VNodeArrayChildren,
      noSlotted?: boolean
    ): VNode {
      let slot = slots[name]
     
      openBlock()
      const validSlotContent = slot && ensureValidVNode(slot(props))
      const rendered = createBlock(
        Fragment,
        { key: props.key || `_${name}` },
        validSlotContent || (fallback ? fallback() : []),
        validSlotContent && (slots as RawSlots)._ === SlotFlags.STABLE
          ? PatchFlags.STABLE_FRAGMENT
          : PatchFlags.BAIL
      )
      return rendered
    }
    

    _renderSlot(_ctx.$slots, "default", {count: _ctx.count})这一句显然是执行_ctx.$slots.default({count: _ctx.count}),这说明在父组件中,每个插槽模板最终会被编译成一个函数,并且这个函数会被传递到子组件,在子组件里面会以props(这里是{count: _ctx.count})作为参数执行插槽函数,最终_ctx.$slots.default({count: _ctx.count})会返回virtual dom对象。

    下面再看一下App.vue组件:

    <Comp>
        <template v-slot="slotProps">
            <p>
                {{magRef}}: {{slotProps.count}}
            </p>
        </template> 
    </Comp>
    

    被编译成了:

    _createVNode(_component_Comp, null, {
        default: _withCtx((slotProps) => [
        _createElementVNode("p", null, _toDisplayString(_ctx.magRef) + ": " + _toDisplayString(slotProps.count), 1 /* TEXT */ )
        ]),
        _: 1 /* STABLE */
    })
    

    请忽略_withCtx,显然模板会编译成一个函数,并传递到子组件,进而在子组件中构建出完整的virtual dom, 上面中_ctx是当前组件的上下文,slotProps则是作用域插槽暴露的参数。

    由此可以做一个总结,vue slot的实现原理:

    1. 所有的模板会被编译成创建vnode的函数。
    2. 父组件中传递给子组件的插槽(每个插槽都是一个函数,即名字不同的插槽为不同的函数)内容模板也会被编译成函数并且传递给子组件,模板中如果使用了父组件的变量,那么会通过闭包的形式在插槽函数中被使用。
    3. 子组件在接收到父组件传递的插槽内容函数,会以在slot暴露的变量(只有作用域插槽有这些变量)为参数执行这个函数,返回vnode,这个vnode会作为子组件vnode的一部分。

    总结

    本文从使用和实现两个方面讲解了vue slot,有一定的深度,但忽略了一些使用和实现上的细节,有不足之处还请指出且谅解。

    展开全文
  • Vue3中的slot

    2021-09-02 19:29:10
    小编今天和大家一起探讨Vue中的插槽(slot)的概念,熟悉Vue的小伙伴都知道父子组件之间可以相互传递数据,但是传递DOM结构的时候,再通过属性的方式就有些麻烦,我们先来看个父子组件的例子 constapp=Vue.createApp...

    小编今天和大家一起探讨Vue中的插槽(slot)的概念,熟悉Vue的小伙伴都知道父子组件之间可以相互传递数据,但是传递DOM结构的时候,再通过属性的方式就有些麻烦,我们先来看个父子组件的例子

    const app= Vue.createApp({    template: `<myform />`})app.component('myform',{    methods:{        handleClick(){            alert('handleClick')        }    },    template: `<div>        <input />        <button @click="handleClick">提交</button>    </div>`})const vm = app.mount("#root")

    上面是一个最基本的父子引用的例子,在父组件中使用的是类似h5中input单标签,有的时候我们会有这样的需求,对于上面的提交,我们有的时候希望渲染成一个按钮,有的时候我们只是希望渲染成普通div。这个时候slot就显示出威力了,我们可以把代码写成这样

    const app= Vue.createApp({    // 将原来的单标签修改为双标签,标签之间的内容会替换掉子组件中的<slot></slot>    template: `<myform>                <div>提交</div>              </myform>              <myform>                <button>提交</button>              </myform>`})app.component('myform',{    methods:{        handleClick(){            alert('handleClick')        }    },    // 不能在slot直接添加@click方式,可以在外面添加span标签    template: `<div>        <input />        <span @click="handleClick">            <slot></slot>        </span>    </div>`})const vm = app.mount("#root")

    其实对于slot,我们肯定不能仅仅满足于此,有的时候也需要进行数据绑定,对于父子组件,遵循的就是父组件中父组件绑定数据,子组件中子组件绑定数据。不会相互混淆

    const app= Vue.createApp({    data(){        return {            f_data:'1234'        }    },    template: `<myform>                <test />            </myform>            <myform>                {{ f_data }}            </myform>`})app.component('myform',{    methods:{        handleClick(){            alert('handleClick')        }    },    template: `<div>        <input />        <span @click="handleClick">            <slot></slot>        </span>    </div>`})
    app.component('test',{    template: `<div>        test component slot    </div>`})const vm = app.mount("#root")

    在定义了slot之后,如果自定义组件之间什么也不传递的话,默认是空字符串,如果我们希望添加默认值的话,可以这样

    const app= Vue.createApp({
        template: `<myform></myform>`})app.component('myform',{    methods:{        handleClick(){            alert('handleClick')        }    },    template: `<div>        <input />        <span @click="handleClick">            <slot>这里是插槽的默认值</slot>        </span>    </div>`})const vm = app.mount("#root")

    有时候我们希望不同的slot渲染不同的内容,这个时候,具名插槽对我们就很有用了,就像这样

    const app= Vue.createApp({    template: `<layout>            // 一定通过template标签,不能将v-slot作用在h5标签上            <template v-slot:header>                <div>header</div>            </template>            <template v-slot:footer>                <div>footer</div>            </template>        </layout>`})app.component('layout',{    template: `<div>        <slot name="header"></slot>        <div>content</div>        <slot name="footer"></slot>    </div>`})const vm = app.mount("#root")

    当然,我们也可以通过#简写成这样

    const app= Vue.createApp({    template: `<layout>            // 通过#替代v-slot            <template #header>                <div>header</div>            </template>            <template #footer>                <div>footer</div>            </template>        </layout>`})app.component('layout',{    template: `<div>        <slot name="header"></slot>        <div>content</div>        <slot name="footer"></slot>    </div>`})const vm = app.mount("#root")

    有时候,我们可能需要在子组件渲染数据,然后在父组件定义不同的标签,这个时候,我们会用到作用域标签

    const app= Vue.createApp({    template: `        <mylist />        // 作用域插槽        <mylist v-slot="slotProps">            <span>{{slotProps.item}}</span>            </mylist>        `})
    app.component('mylist',{    data(){        return {            list: [1,2,3]        }    },    template: `<div>            <slot v-for="item in list" :item="item"></slot>        </div>`})const vm = app.mount("#root")

    大家还可以扫描二维码,关注我的微信公众号,蜗牛全栈

     

     

    展开全文
  • Vue2入门之slot

    2021-03-03 11:11:05
    1.slot是干啥的? 假如父组件需要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪个地方显示、如何显示,就是slot分发负责的活。 2.在父组件中,子组件标签里内套的内容,是不显示的。 //子组件 <template...

    1.slot是干啥的?

    假如父组件需要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪个地方显示、如何显示,就是slot分发负责的活。

    2.在父组件中,子组件标签里内套的内容,是不显示的。

    //子组件
    <template>
        <div>
            <h3>我是子组件</h3>
        </div>
    </template>
    
    //父组件
    <template>
      <div>
          //hello不显示
          <v-child>hello</v-child>
      </div>
    </template>
    

    以上hello是不显示的,只会显示我是子组件

    3.使用slot标签,就可以将父组件放在子组件标签里的内容,放到想让他显示的地方。

    //子组件
    <template>
        <div>
            <h3>我是子组件</h3>
            <slot></slot>//加了个slot标签,在父组件中,就可以让子组件标签内的内容显示啦
        </div>
    </template>
    
    //父组件
    <template>
      <div>
          //hello显示
          <v-child>hello</v-child>
      </div>
    </template>
    

    就相当于子组件标签里的内容,插到了子组件中的<slot></slot>位置;
    即使有多个标签,会一起被插入,相当于用父组件放在子组件里的标签,替换了这个标签。

    4.具名slot

    将放在子组件里的不同html标签放在不同的位置
    子组件在对应分发的位置的slot标签里,添加<slot name='name名' >内容</slot>属性,
    父组件在要显示的标签里添加 slot='name名'属性,比如要在p标签中显示子组件对应的dom,<p slot='name名'></p>
    然后就会将对应的标签放在对应的位置了。该slot标签没有内容,会显示子组件中该slot标签内的内容。

    //子组件
    <template>
        <div>
            <h3>我是子组件</h3>
            <p><slot name="header">父组件中没header的时候会显示</slot></p>
            <p><slot name="footer">父组件中没footer的时候会显示</slot></p>
        </div>
    </template>
    
    //父组件
    <template>
      <div>
          <v-child>
              <p>hello</p>
              <h3 slot="header">header</h3>
          </v-child>
      </div>
    </template>
    

    显示结果:
    我是子组件
    header
    父组件中没footer的时候会显示

    5.分发内容的作用域

    被分发的内容的作用域,根据其所在模板决定,例如,v-child标签里的东西,其在父组件的模板中(虽然其被子组件的v-child标签所包括,但由于他不在子组件的template属性中,因此不属于子组件),则受父组件所控制。
    举个栗子:在父组件中定义一个方法,在子组件中写个按钮,按钮包裹slot标签

    //子组件
    <template>
        <div>
            <h3>我是子组件</h3>
            <button><slot name="header">父组件中没header的时候会显示</slot></button>
            <p><slot name="footer">父组件中没footer的时候会显示</slot></p>
        </div>
    </template>
    
    //父组件
    <template>
      <div>
          <v-child>
              <p>hello</p>
              <h3 slot="header" @click="clickBtn">header</h3>
              <h3 slot="footer">footer</h3>
          </v-child>
      </div>
    </template>
    <script>
    import child from './components/child.vue'
    export default {
      data () {
        return {
          child_data: ''
        }
      },
      components: {
        'v-child': child
      },
      methods: {
        clickBtn () {
          console.log('Hello')
        }
      }
    }
    </script>
    

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

    当点击文字header的区域时(而不是按钮全部),会触发父组件的clickBtn方法,但是点击其他区域时则没有影响。
    是由于header是由子组件中的slot替换的,作用域数据父组件中的
    官网文档这样说:
    父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译;

    6.没有分发时内容的提示

    如果父组件与自组件有对应的name。
    那么父组件优先,<slot>xx</slot>,xx不会显示
    如果没有对应的name
    那么子组件内的<slot>xxx</slot>,xxx 将会被展开,<slot>标签被删除。栗子在第4条的例子里面可以体现

    7.父组件控制子组件内部的方法

    【1】首先,由于模板标签是属于父组件的,因此,将子组件的指令绑定在模板标签里,是不可以的(因为他归属于父组件);
    【2】假如需要通过父组件控制子组件是否显示(例如v-if或者v-show),那么这个指令显然是属于父组件的(例如放在父组件的data下面)。可以将标签写在子组件的模板上。
    举个栗子:

    //子组件
    <template>
        <div>
            <h3>我是子组件</h3>
        </div>
    </template>
    
    //父组件
    <template>
      <div>
          <button @click="showChild">点击显示子组件</button>
          <v-child v-if="show"></v-child>
      </div>
    </template>
    <script>
    import child from './components/child.vue'
    export default {
      data () {
        return {
          show: false
        }
      },
      components: {
        'v-child': child
      },
      methods: {
        showChild () {
          this.show = !this.show
        }
      }
    }
    </script>
    

    结果:
    在这里插入图片描述
    通过父组件(点击按钮,切换v-if指令的值)控制子组件是否显示是可以的。
    【3】假如需要通过子组件,控制子组件是否显示(比如让他隐藏),那么这个指令显然是属于子组件的(会将值放在子组件的data属性下),那么就不能像上面这么写,而是必须放置在子组件的根标签中。

    作用域插槽

    就是用来传递数据的插槽

    当你想在一个插槽中使用数据时,要注意一个问题作用域的问题,Vue 官方文档中说了父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的;

    为了让 子组件中的数据 在父级的插槽 内容中可用我们可以将 数据 作为 元素的一个特性绑定上去: v-bind:text="text"

    注意:

    匿名的作用域插槽和具名的作用域插槽 区别在v-slot:defult="接受的名称"(defult(匿名的可以不写,具名的相反要写的是对应的name))
    v-solt可以解构接收 解构接收的字段要和传的字段一样才可以 例如 :one 对应 v-slot="{one}"
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • vue2 写法: <div slot="header"> <i class="el-icon-menu"></i> 销售明细 </div> vue3 写法: <template v-slot:header> <div> <i class="el-icon-menu"></...

    背景介绍:

    工作的时候是一直都在用vue2 + element2 写的前端,最近突然被安排做别的项目,项目已经用vue3 + elementPlus 搭的框架, 虽然核心内容都差不多,但是有些写法已被废弃,写篇文章记录一下。

    vue2 写法:

    <div slot="header">
        <i class="el-icon-menu"></i>
        销售明细
    </div>

    vue3 写法:

    <template v-slot:header>
        <div>
            <i class="el-icon-menu"></i>销售明细
        </div>
    </template>

    注意点:

    • v-slot:header 要写在 template 标签里 ,写在 div 标签里会报错,如图所示。

    最后结果:

    一个好看的自带底部分割线的header

    展开全文
  • Vue3 中插槽(slot)的用法

    万次阅读 2021-02-03 14:55:53
    Vue3 中插槽(slot)的用法 概要 Vue3(其实从2.6开始)中引入了一个新的指令v-slot,用来表示具名插槽和默认插槽 基础示例 <!-- default slot --> <foo v-slot="{ msg }"> {{ msg }} </foo> <...
  • vue插槽(slot)详解

    2021-03-04 17:33:28
    最近被问起是否了解vue的插槽(slot),咋一想发现,似乎很少用到这玩意。所以整理了下slot的一些用法。 slot (父组件 在子组件<slot> </slot>处插入内容) Vue 实现了一套内容分发的 API,将<slot&...
  • vue3中插槽slot的使用

    2021-04-28 18:55:38
    子组件中的代码: <template> <div class="navBox"> <div class="menus"> div> <slot name="headerBox">slot> <div class="user">div> div> <style> .navBox{ display:flex } style> <template> vue3 中插槽的...
  • 这次给大家带来vue父子组件传值及slot应用步骤详解,vue父子组件传值及slot应用的注意事项有哪些,下面就是实战案例,一起来看一下。一.父子组件传值父子组件传值{{total}}//父组件向子组件传值用 props ,加:号后...
  • slot 插槽,主要用来做内容分发主要有三种操作方式:默认插槽具名插槽作用域插槽默认插槽没有太多的逻辑,就是把父组件的内容分发到子组件的指定位置// 父组件{{msg}} // 子组件我是作用域插槽的子组件默认内容具名...
  • template v-slot:default> 任意内容 <p>我是匿名插槽 </p> </template> </todo-list> 子 <slot>我是默认值</slot> 具名插槽 比上面的好点有个名字 父 <todo-list&...
  • vue2.x中slot-scope插槽在vue3.x中的新写法 1.vue2.x的写法 <el-table-column label="测试" align="center" prop="ce"> <template slot-scope="scope"> //2.x的写法 <span>{{scope.row.ce}}<...
  • vue 3.x 插槽v-slot升级table组件

    千次阅读 2021-01-27 19:23:41
    1.需求:iview的table组件提供了自定义列模板的方式,使用slot-scop,结构出我们需要的数据项,极大方便了我们的开发,现在我们用vue3.x的v-slot来升级这种自定义列模板的写法。 2.子组件,slot上命名每一项的数据的...
  • slot 默认使用其他传进来的 slot 值,并且还支持对当前的 slot 修改
  • Vue slot 跨组件传递

    2021-11-15 21:10:27
    Vue slot 跨组件传递、Vue slot 透传、Vue slot 多级传递、 很多情况下,我们需要使用到嵌套组件,嵌套组件中深层的组件如何获取外部传进来的 slot 呢?
  • vue3中Slot常见使用

    2021-10-06 11:44:49
    下面先来认识一下插槽 在开发中,我们会经常封装一个个可复用的组件: 前面我们会通过props传递给组件一些数据,...同时会将不同的元素使用slot作为占位,让外部决定到底显示什么样的元素; 在封装组件中,使用特殊的
  • Vue新指令:v-slot

    2021-07-15 03:05:07
    在《Vue组件内容分发》和《Vue的作用域插槽》文章中我们深入的学习了slot怎么在Vue中的使用,但在Vue 3.0版本为slot引入了一套全新的模版语法。为了更好的从2.x过渡到3.0,Vue的v2.6版本引入了新的slot语法,即 v-...
  • 作用域HEi免费资源网在介绍slot前,需要先知道一个概念:编译的作用域。比如父组件中有如下模板:HEi免费资源网{{message}}这里的message就是一个slot,但是它绑定的是父组件的数据,而...HEi免费资源网Vue.compo...
  • vueslot 的具体用法

    2020-12-24 04:45:54
    子组件 {{item.text}} 父组件 首页 跳转到详情 父组件 {{msg}} 这种情况是如果要父组件在子组件中插入内容 ,必须要在子组件中声明slot标签 ,如果子组件模板不包含插口,父组件的内容 {{msg}}将会被丢弃。 当slot...
  • Vueslot的常见用法

    2021-05-26 10:50:01
    Vue中的Slot对于编写可复用可扩展的组件是再合适不过了,常见的用法有以下3种: 1. 插入一个匿名的Slot,匿名的情况只适用于只插入一个的时候; 2. 插入有名的Slot,当插入的Slot有多个的时候,需要按名占位; 3....
  • slot 英文的意思是“插槽”的意思,vue用这个词做标签,意思是能够在这个标签里插入一些东西,是由调用组件(父组件)向其调用的子组件里插入一些东西的一个解决办法。 slot的语法如下: <slot></slot&...
  • 在开发过程中遇到这样一个...我们在开发过程中,希望可以这样实现重新定义叶子节点的结构:{{data.title}} - {{data.text}}那么如何在组件内传递Slot就是一个问题。嵌套传递通过固定级别的组件结构里可以通过直接...
  • 按照vue文档上所说里面的v-slot:child应该是能渲染的,但是现在我这样写却没有渲染出这个插槽组件,请问如何才能在渲染函数中使用slot属性?子组件插槽默认插槽var childNode = {props: {},data () {return {user: {...
  • vue中的slot标签

    2021-11-23 12:14:20
    (二十八)Slot分发内容 ①概述: 简单来说,假如父组件需要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪个地方显示、如何显示,就是slot分发负责的活。 ②默认情况下 父组件在子组件内套的内容,是不显示...
  • 不过正好 Vue2.6 中把普通插槽和作用域插槽给合并了,顺便说一说。先说结论,后证明:结论一:插槽就是一个返回VNode的函数而已。结论二:普通插槽和作用域插槽根本就没有区别,因为普通插槽就是作用域插槽的子集,...
  • vue 3.0 slot 使用方法

    2021-04-13 10:04:54
    import { defineComponent, PropType } from 'vue' interface Post { title: string, content: string, } export default defineComponent({ name: 'post', props: { blog: { type: Object as PropType<...
  • vueslot的使用

    2021-12-09 09:25:33
    vue slot基本用法
  • 三、Vue插槽slot的用法

    2021-09-09 09:10:14
    插槽slot 一、基本使用 使组件具备扩展性 <div id = 'app'> <cpn1><p>11111</p></cpn1> <cpn1><button>按钮</button></cpn1> </div> <...
  • vue slot的原理

    2021-04-27 16:05:33
    Vue.component('button-counter', { template: '<div> <slot>我是默认内容</slot></div>' }) 这个组件生成的渲染函数 (function anonymous( ) { with(this){return _c('div',[_t("default...
  • 1.认识插槽Slot 在开发中,我们会经常封装一个个可复用的组件: 前面我们会通过props传递给组件一些数据,让组件来进行展示; 但是为了让这个组件具备更强的通用性,我们不能将组件中的内容限制为固定的div、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 51,609
精华内容 20,643
关键字:

slotvue

vue 订阅