vue slot使用,v-slot vue

  vue slot使用,v-slot vue

  本文主要介绍了Vue中slot使用的详细讲解,有很好的参考价值,希望对大家有所帮助。如有错误或不足之处,请不吝赐教。

  

目录

  使用slot基本用法命名slot作用域Slot实现总结在Vue中,我们使用组件来组织页面和代码,类似于积木。每个组件都是一个构建块,我们可以通过使用一些相同或不同的组件来构建所需的页面。

  插槽(Slot)是组件功能的重要组成部分,插槽必须用于组件才有意义。

  它为组件提供了一个外部接口,允许从组件外部交付内容,并将这部分内容放在指定的位置。

  

使用 slot

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

  

基础用法

  Link.vue

  模板

  a:href= href rel= external no follow class= link

  !-留出一个可以放置外部传入内容的插槽-

  插槽/插槽

  /a

  /模板

  脚本

  导出默认值{

  道具:{

  href: {

  必填:真,

  类型:字符串,

  },

  },

  };

  /脚本

  style lang=less 范围。链接{

  显示:内嵌-块;

  行高:1;

  空白:nowrap

  光标:指针;

  背景:# fff

  边框:1px solid # dcdfe6

  颜色:# 606266;

  -WebKit-外观:无;

  文本对齐:居中;

  框大小:边框-框;

  大纲:无;

  边距:0;

  转场:0.1s

  字体粗细:500;

  填充:12px 20px

  字体大小:14px

  边框-半径:4px

  }

  /风格

  App.vue

  模板

  div class=" app "

  Link= 3359 Baidu . com rel= external no follow Baidu/Link

  br /

  link href= https://Google . com rel= external no follow style= margin-top:10px

  !-此处允许任意内容,包括字符串和标签-

  Spanicon/spangoogle /Link

  /div

  /模板

  脚本

  从导入链接。/link . vue ;

  导出默认值{

  组件:{

  链接,

  },

  };

  /脚本

  视觉效果:

  实现了上面两个组件Link.vue和App.vue。Link.vue是一个链接的组件,在组件内部已经定义了样式,然后外部世界使用的时候填充链接的内容。

  在App.vue组件中,Link.vue组件使用了两次,传入的内容是不同的。

  

具名插槽

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

  Page.vue

  模板

  div class=page

  header class=page-header

  插槽名称=header/slot

  /页眉

  div class=page-center

  撇开不谈

  插槽名称=备用/插槽

  /抛开

  div class=页面内容

  槽名=内容/槽

  /div

  /div

  页脚class=页脚

  插槽名称=页脚/插槽

  /页脚

  /div

  /模板

  脚本

  导出默认值{

  setup() {

  return { };

  },

  };

  /脚本

  style lang=less

  正文{

  边距:0;

  }。页面{

  边框:1px纯色# 333;

  宽度:100vw

  身高:100vh

  显示器:flex

  伸缩方向:列;

  -标题{

  高度:50px

  边框-底部:1px solid # 333333

  }

  -中心{

  flex:1;

  显示器:flex

  }

  -靠边站

  宽度:150px

  右边框:1px solid # 333333

  }

  -内容{

  flex:1;

  }

  -页脚{

  border-top:1px solid # 333;

  高度:30px

  }

  }

  /风格

  App.vue

  模板

  页面样式= width:500 px;高度:300px边距:30px 30px

  模板v-slot:header这是标题/模板。

  模板v槽:旁边这是侧边栏/模板。

  模板v槽:内容这是内容区域/模板

  模板v槽:页脚这是页脚/模板。

  /页面

  页面样式= width:500 px;高度:300px边距:30px 30px

  模板v形槽:标题

  H2路过/h2

  /模板

  模板v形槽:侧面

  保险商实验所

  东方的李杰石/李

  李看海/李

  /ul

  /模板

  模板v槽:内容这是内容区域/模板

  模板v槽:页脚这是页脚/模板。

  /页面

  /模板

  脚本

  从导入页面。/page . vue ;

  导出默认值{

  组件:{

  页面,

  },

  };

  /脚本

  效果图:

  

作用域插槽

  为什么叫范围槽?首先要理解范围的概念。在JS中,作用域代表当前的执行上下文,变量只能在当前的作用域中使用。范围分为父范围和子范围。子作用域可以访问父作用域中的变量,作用域链是从每一层向上形成的。JS只有全局作用域和函数作用域,ES6有了新的块级作用域。关于范围,这里不再赘述。有需要的同学可以去MDN的范围看看。

  Vue本质上是js,模板最终会编译成渲染函数。每个组件都有一个渲染函数。我们先来看一个例子:

  Count.vue

  模板

  差异

  p当前号码:{{ count }}/p

  button @click=onAdd /button

  button @click=onMinus-/button

  插槽/插槽

  /div

  /模板

  脚本

  导出默认值{

  data() {

  返回{

  计数:0,

  };

  },

  方法:{

  onAdd() {

  this.count

  },

  onMinus() {

  this . count-;

  },

  },

  };

  /脚本

  App.vue

  模板

  差异

  Count style=border: 1px纯红

  p这是填充计数组件的插槽/p

  pappCount:{{ appCount }}/p

  pCount组件中的计数变量:{{ count }}/p

  /计数

  br /

  button @click=onClick 应用添加/button

  /div

  /模板

  脚本

  从导入计数。/count . vue ;

  导出默认值{

  组件:{

  数数,

  },

  data() {

  返回{

  appCount: 0,

  };

  },

  方法:{

  onClick() {

  this . app count;

  },

  },

  };

  /脚本

  效果图:

  从上面的渲染图可以看出,在App.vue组件中使用Count.vue组件时,在Count.vue组件的槽中,可以访问appCount变量,但是不能访问Count.vue组件的Count变量。为什么?理论上,插槽的输入内容最终会被插入到Count.vue组件中,因此Count.vue组件的变量也应该是可访问的。

  父模板中的所有内容都在父范围内编译;子模板中的所有内容都在子范围内编译。

  以上引文摘自Vue文档,表示App.vue中的一切,包括Count.vue组件的slot内容,都是在App.vue组件下编译的,即Count.vue组件的slot模板可以访问App.vue组件的所有变量,但不能访问Count.vue组件的任何变量。如果我必须访问插槽中Count.vue的count变量怎么办?这就是scope插槽派上用场的时候了。

  Scope slot允许一些变量暴露给组件中slot所在的上下文,覆盖上面的Count.vue组件,

  Count.vue

  模板

  差异

  p当前号码:{{ count }}/p

  button @click=onAdd /button

  button @click=onMinus-/button

  !-向插槽范围公开count变量-

  slot :count=count/slot

  /div

  /模板

  脚本

  导出默认值{

  data() {

  返回{

  计数:0,

  };

  },

  方法:{

  onAdd() {

  this.count

  },

  onMinus() {

  this . count-;

  },

  },

  };

  /脚本

  App.vue

  模板

  差异

  Count style=border: 1px纯红

  !- Count组件slot公开的所有变量都放在slotProps对象中-

  模板v-slot=slotProps

  p这是填充计数组件的插槽/p

  pappCount:{{ appCount }}/p

  pCount组件中的Count变量:{{ slotProps.count }}/p

  /模板

  /计数

  br /

  button @click=onClick 应用添加/button

  /div

  /模板

  脚本

  从导入计数。/count . vue ;

  导出默认值{

  组件:{

  数数,

  },

  data() {

  返回{

  appCount: 0,

  };

  },

  方法:{

  onClick() {

  this . app count;

  },

  },

  };

  /脚本

  这是作用域插槽。本质上,它允许访问父组件范围中的子组件范围。它为插槽模板区域提供了一个上下文,数据来自子组件。

  作用域插槽的用处还是挺广的,总的来说当你需要它时自然会用到它,如果想提前学习,可以看一下elementUI的桌子组件。

  

slot 实现

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

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

  比较某视频剪辑软件

  模板

  差异

  pcount: {{count}}/p

  button @click=onClick

  模拟数字音乐制碟

  /按钮

  slot :count=count/slot

  /div

  /模板

  脚本

  从“vue”导入{定义组件,引用}

  导出默认定义组件((道具)={

  const count=ref(0);

  const onClick=()={

  计数。值

  }

  返回{

  数数,

  单击事件

  }

  })

  /脚本

  App.vue

  模板

  差异

  免费票

  模板v-slot=slotProps

  p

  {{magRef}}: {{slotProps.count}}

  /p

  /模板

  /Comp

  /div

  /模板

  脚本

  从“vue”导入{定义组件,引用}

  从导入排版 Comp.vue

  导出默认定义组件({

  组件:{Comp},

  设置(道具){

  const magRef=ref(当前的数字是)

  返回{

  马格雷夫

  }

  }

  })

  /脚本

  比较某视频剪辑软件编译之后:

  /*分析的绑定:{} */

  导入{

  定义一个组件,

  裁判员

  }来自“vue”

  const _ _ sfc _ _=定义组件((props)={

  const count=ref(0);

  const onClick=()={

  计数。值

  }

  返回{

  数数,

  单击事件

  }

  })

  导入{

  toDisplayString as _ toDisplayString,

  createElementVNode as _ createElementVNode,

  renderSlot as _renderSlot,

  openBlock as _openBlock,

  createElementBlock as _ createElementBlock

  }来自“vue”

  函数呈现(_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。在线点击CTX。onclick(.args)))

  }、添加),

  _renderSlot(_ctx .$老虎机,默认,{

  计数:_ctx.count

  })

  ]))

  }

  __sfc__ .渲染=渲染

  __sfc__ .__file=Comp.vue

  导出默认值__sfc__

  App.vue编译之后:

  /*分析的绑定:{} */

  导入{

  定义一个组件,

  裁判员

  }来自“vue”

  从导入排版 Comp.vue

  const __sfc__=defineComponent({

  组件:{

  免费票

  },

  设置(道具){

  const magRef=ref(当前的数字是)

  返回{

  马格雷夫

  }

  }

  })

  导入{

  toDisplayString as _ toDisplayString,

  createElementVNode as _ createElementVNode,

  将组件解析为_ resolve组件,

  withCtx as _withCtx,

  createVNode as _createVNode,

  openBlock as _openBlock,

  createElementBlock as _ createElementBlock

  }来自“vue”

  函数呈现(_ctx,_cache,$props,$setup,$data,$options) {

  const _ component _ Comp=_ resolve component( Comp )

  return (_openBlock(),_createElementBlock(div ,null,[

  _createVNode(_component_Comp,null,{

  默认值:_ witchtx((老虎机道具)=[

  _createElementVNode(p ,null,_ toDisplayString(_ CTX。mag ref): _ toDisplayString(slot props。计数),1 /* TEXT */)

  ]),

  _: 1 /*稳定*/

  })

  ]))

  }

  __sfc__ .渲染=渲染

  __sfc__ .__file=App.vue

  导出默认值__sfc__

  这里给大家推荐一个尤雨溪搞的测试网站Vue SFC游乐场可以直接看到组件编译之后的射流研究…代码。

  这个编译是在加载。某视频剪辑软件文件的时候就执行了,运行时阶段是不存在模板字符串了(使用UMD的时候会存在),在浏览器中执行的都是编译之后的js。下面具体分析一下以上比较某视频剪辑软件和App.vue编译之后的射流研究…代码。

  首先在比较某视频剪辑软件中,slot :count=count/slot会被编译成_renderSlot(_ctx .$slots, default ,{count: _ctx.count}),下面看看_renderSlot中干了什么?

  导出类型插槽=(.args: any[])=VNode[]

  导出类型内部插槽={

  [名称:字符串]:插槽未定义

  }

  导出函数renderSlot(

  插槽:插槽,

  名称:字符串,

  道具:Data={},

  //这不是面向用户的函数,因此回退总是由

  //编译器,并保证是返回数组的函数

  退路?()=VNodeArrayChildren,

  没有抽签?布尔型

  ):VNode {

  let slot=slots[name]

  openBlock()

  const validSlotContent=slot ensureValidVNode(slot(props))

  const rendered=createBlock(

  片段,

  { key: props.key `_${name}` },

  validSlotContent (回退?回退():[]),

  validSlotContent(作为原始插槽的插槽)。_===插槽标志。稳定的

  ?补丁标志。稳定碎片

  :修补标志。保释

  )

  渲染返回

  }

  句子_渲染槽(_ ctx。$ slots, default ,{count: _ ctx.count})显然是为了execute _ ctx。$ slots . default({count: _ ctx.count}),意思是在父组件中,每个slot模板最终都会被编译成一个函数,而这个函数会被传到子组件中,slot函数会以props(这里是{ count:_ ctx . count })为参数执行,最后是_ CTX。$ slots . default({ count:_ CTX . count })将返回虚拟dom对象。

  让我们再来看看App.vue组件:

  免费票

  模板v-slot=slotProps

  p

  {{magRef}}: {{slotProps.count}}

  /p

  /模板

  /Comp

  编译成:

  _createVNode(_component_Comp,null,{

  默认值:_ witchtx((slot props)=[

  _createElementVNode(p ,null,_ toDisplayString(_ CTX . magref): _ toDisplayString(slot props . count),1 /* TEXT */)

  ]),

  _: 1 /*稳定*/

  })

  请忽略_withCtx。很明显,模板会被编译成一个函数并传递给子组件,然后在子组件中构建一个完整的虚拟dom。在上面,_ctx是当前组件的上下文,slotProps是作用域slot公开的参数。

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

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

  

总结

  本文从使用和实现两个方面来解释vue slot,有一定的深度,但是忽略了一些使用和实现的细节。请指出并理解不足之处。

  以上个人经历,希望能给大家一个参考,也希望大家多多支持我们。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: