丽品优系统开发

37次阅读

共计 2360 个字符,预计需要花费 6 分钟才能阅读完成。

普通的插槽里面的 丽品优系统开发(T:I8O-285I-O282 v 林),而作用域插槽里的数据是在子组件定义的。

有时候作用域插槽很有用,比如使用 Element-ui 表格自定义模板时就用到了作用域插槽,Element-ui 定义了每个单元格数据的显示格式,我们可以通过作用域插槽自定义数据的显示格式,对于二次开发来说具有很强的扩展性。


作用域插槽使用 <template> 来定义模板,可以带两个参数,分别是:

 slot-scope    ; 模板里的变量,旧版使用 scope 属性

 slot              ; 该作用域插槽的 name, 指定多个作用域插槽时用到,默认为 default,即默认插槽

例如:

复制代码
<!DOCTYPE html>
<html lang=”en”>
<head>

<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

</head>
<body>

<div id="app">
      <Child>
        <template slot="header" slot-scope="props">                 <!-- 定义了名为 header 的作用域插槽的模板 -->
          <h1>{{props.info.name}}-{{props.info.age}}</h1>
        </template>
        <template slot-scope="show">                                <!-- 定义了默认作用域插槽的模板 -->
          <p>{{show.today}}</p>
        </template>
      </Child>
  </div>
  <script>
    Vue.config.productionTip=false;
    Vue.config.devtools=false;
    Vue.component('Child',{
      template:`<div class="container">
                    <header><slot name="header" :info="info"></slot></header>     //header 插槽
                    <main><slot today="礼拜一"> 默认内容 </slot></main>               // 默认插槽
                </div>`,
          data(){return { info:{name:'ge',age:25} }
          }
    })
    debugger
    new Vue({
      el: '#app',
      data:{
        title:'我是标题',
        msg:'我是内容'
      }
    })
  </script>

</body>
</html>
复制代码
我们在子组件定义了两个插槽,如下:

 header 插槽内通过 v -bind 绑定了一个名为 info 的特性,值为一个对象,包含一个 name 和 age 属性

 另一个是普通插槽,传递了一个 today 特性,值为礼拜一

父组件引用子组件时定义了模板,渲染后结果如下:

对应的 html 代码如下:

其实 Vue 内部把父组件 template 下的子节点编译成了一个函数,在子组件实例化时调用的,所以作用域才是子组件的作用域

源码分析

父组件解析模板将模板转换成 AST 对象时会执行 processSlot()函数,如下:

复制代码
function processSlot (el) {// 第 9767 行 解析 slot 插槽
if (el.tag === ‘slot’) {// 如果是 slot

/* 普通插槽的逻辑 */

} else {

var slotScope;
if (el.tag === 'template') {// 如果标签名为 template(作用域插槽的逻辑)
  slotScope = getAndRemoveAttr(el, 'scope');          // 尝试获取 scope
  /* istanbul ignore if */  
  if ("development" !== 'production' && slotScope) {  // 在开发环境下报一些信息,因为 scope 属性已淘汰,新版本开始用 slot-scope 属性了
    warn$2(
      "the \"scope\"attribute for scoped slots have been deprecated and" +
      "replaced by \"slot-scope\"since 2.5. The new \"slot-scope\"attribute" +
      "can also be used on plain elements in addition to <template> to" +
      "denote scoped slots.",
      true
    );
  }
  el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope'); // 获取 slot-scope 特性,值保存到 AST 对象的 slotScope 属性里
} else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {/* 其它分支 */}
var slotTarget = getBindingAttr(el, 'slot');          // 尝试获取 slot 特性
if (slotTarget) {                                     // 如果获取到了
  el.slotTarget = slotTarget === '""'?'"default"' : slotTarget;   // 则保存到 el.slotTarget 里面
  // preserve slot as an attribute for native shadow DOM compat
  // only for non-scoped slots.
  if (el.tag !== 'template' && !el.slotScope) {addAttr(el, 'slot', slotTarget);
  }
}

}
}
复制代码
执行到这里,对于 <template slot=”header” slot-scope=”props”> 节点来说,添加了一个 slotScope 和 slotTarget 属性

正文完
 0