Vue插槽、ref和$refs用法

1.vue插槽

1.插槽的做用:以局部组件为例

  插槽就是Vue实现的一套内容分发的API,将<slot></slot>元素做为承载分发内容的出口。插槽内能够是任意内容。vue

(1)不带插槽的状况:api

<div id="app">
            <vue>
                <h2>我是里面的内容</h2></vue>
        </div>

        <script>
            var Child = { template: '<div><h1>自定义组件!</h1></div>' } // 建立根实例
            new Vue({ el: '#app', components: { // <vue> 将只在父模板可用
                    'vue': Child } }) </script>

结果:组件标签内的元素不会显示app

 

(2)带插槽的状况:标签内部的元素会被置于<slot></slot>的位置dom

<div id="app">
            <vue>
                <h2>我是里面的内容</h2></vue>
        </div>

        <script>
            var Child = { template: '<div><h1>自定义组件!</h1><slot></slot></div>' } // 建立根实例
            new Vue({ el: '#app', components: { // <vue> 将只在父模板可用
                    'vue': Child } }) </script>

结果:函数

 

 2.编译做用域

  父级模板里的全部内容都是在父级做用域中编译的;子模板里的全部内容都是在子做用域中编译的。spa

  插槽跟模板的其它地方同样能够访问相同的实例属性 (也就是相同的“做用域”),而不能访问 插槽上的属性。3d

以下:slot内部能够访问到vue实例的msg属性,访问不到组件的message属性。code

<div id="app">
            <vue message="message123">
                <h2>{{msg}}</h2>
                <h2 v-if="typeof  message != 'undefined'">{{message}}</h2>
                <h2 v-else>访问不到message属性</h2>
            </vue>
        </div>

        <script>
            var Child = { template: '<div><h1>自定义组件!</h1><h2>{{message}}</h2><br/><slot></slot></div>', // 声明 props属性
                props: ['message'], } // 建立根实例
            new Vue({ el: '#app', components: { // <vue> 将只在父模板可用
                    'vue': Child }, data: { msg: '这是msg' } }) </script>

结果:component

 

 3.带有 slot-scope 特性的做用域插槽

  在组件上的属性,能够在组件元素内使用!对象

(1)  在 <template> 上使用特殊的 slot-scope 特性,能够接收传递给插槽的 prop

<div id="app">
            <child>
                <template slot-scope="a"> {{a}} <br /> {{a.username}} </template>
            </child>
        </div>
        <script> Vue.component('child', { template: ` <div>
                <slot username="张三"></slot>
            </div>
 ` }) let vm = new Vue({ el: '#app' }) </script>

结果:

 

 解释:

(1)组件中的<slot username="张三"></slot>定义了一个属性,

(2)slot-scope 声明了被接收的 a 对象会做为 a 变量存在于 <template> 做用域中。你能够像命名 JavaScript 函数参数同样随意命名 a

(3)slot-scope 特性也能够直接用于非 <template> 元素 (包括组件):

<child>
                <h3 slot-scope="a">{{a}}=={{a.username}}</h3>
            </child>

结果:

 

 (2)获取组件上值

<div id="app">
            <child componentmsg="123456">
                <h3 slot-scope="a">{{a}}</h3>
            </child>
        </div>
        <script> Vue.component('child', { props: ['componentmsg'], template: ` <div>
                <slot :slotmsg="componentmsg"></slot>
            </div>
 ` }) let vm = new Vue({ el: '#app' }) </script>

结果:

 (3)获取vue实例属性:(组件的属性动态获取实例的属性)

<div id="app">
            <child :componentmsg="vueMsg">
                <h3 slot-scope="a">{{a}}</h3>
            </child>
        </div>
        <script> Vue.component('child', { props: ['componentmsg'], template: ` <div>
                <slot :slotmsg="componentmsg"></slot>
            </div>
 ` }) let vm = new Vue({ el: '#app', data: { vueMsg: '这是实例属性' } }) </script>

结果:

 

补充:自 2.6.0 起有所更新。上面使用 slot-scope 特性的语法已经废弃。2.6之后作法以下:绑定在 <slot> 元素上的特性被称为插槽 prop。如今在父级做用域中,咱们能够给 v-slot 带一个值来定义咱们提供的插槽 prop 的名字: 

<div id="app">
            <child :user="user">
                <template v-slot:default="slotProps"> {{ slotProps.user.firstName }}</template>
            </child>
        </div>
        <script> Vue.component('child', { props: ['user'], template: ` <div>
                <slot v-bind:user="user"></slot>
            </div>
 ` }) let vm = new Vue({ el: '#app', data: { user: { lastname: '张', firstName: '三' } } }) </script>

结果:

 4..具名插槽

  有时候咱们可能须要多个插槽。slot有一个特殊的属性,name能够用于定义额外的插槽。

例如:不带名称的默认都会被放在无名称的slot内。

<div id="app">
            <vue>
                <template slot="h1s">
                    <p>这里是h1的内容</p>
                </template>
                <template slot="h2s">
                    <b><p>这里是h2的内容</p></b>
                </template>
                <p slot="h1s">这里是其余内容</p>
                <p>这里是其余内容</p>
            </vue>
        </div>

        <script>
            var Child = { template: '<div><h1><slot name="h1s"></slot></h1><h2><slot name="h2s"></slot></h2><br/><hr/><slot></slot></div>' } // 建立根实例
            new Vue({ el: '#app', components: { // <vue> 将只在父模板可用
                    'vue': Child }, data: { msg: '这是msg' } }) </script>

结果:

补充:上面是vue2.6以前的写法,vue2.6以后有所区别:

(1)一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

(2)在向具名插槽提供内容的时候,咱们能够在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称

(3)任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。

(4)注意 v-slot 只能添加在 <template> 上

<div id="app">
            <vue>
                <template v-slot:h1s>
                    <p>这里是h1的内容</p>
                </template>
                <template v-slot:h2s>
                    <b><p>这里是h2的内容</p></b>
                </template>
                <!--v-slot:default能够不写,默认都是default插槽的-->
                <template v-slot:default>
                    <b><p>这里是其余内容</p></b>
                </template>
            </vue>
        </div>

结果:

 

缩写:2.6.0 新增

跟 v-on 和 v-bind 同样,v-slot 也有缩写,即把参数以前的全部内容 (v-slot:) 替换为字符 #。例如 v-slot:h1s 能够被重写为 #h1s:

<vue>
                <template #h1s>
                    <p>这里是h1的内容</p>
                </template>
                <template #h2s>
                    <b><p>这里是h2的内容</p></b>
                </template>
                <!--v-slot:default能够不写,默认都是default插槽的-->
                <template #default>
                    <b><p>这里是其余内容</p></b>
                </template>
            </vue>

 

5.动态插槽名

  vue2.6新增了动态参数,能够用方括号括起来的 JavaScript 表达式做为一个指令的参数。

例如:

<a v-on:[eventName]="doSomething"> ... </a>

  在这个示例中,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus。

 

动态指令参数也能够用在 v-slot 上,来定义动态的插槽名:

<base-layout>
  <template v-slot:[dynamicSlotName]> ... </template>
</base-layout><base-layout>
  <template v-slot:[dynamicSlotName]> ... </template>
</base-layout>

 

2.ref和$ref的使用

  ref被用来给组件或子元素注册引用信息,引用信息将会注册在父组件的$ref属性上。

  vm.$refs是一个只读属性,返回值是一个对象,持有注册过 ref 特性 的全部 DOM 元素和组件实例。。

 

  若是在普通的dom上使用,引用指向的就是DOM对象 ,$refs相对document.getElementById的方法,会减小获取dom节点的消耗。;若是用在子组件上,引用指向组件实例。

例如:

<div id="app">
            <p ref="pref">p内容</p>
            <child ref="child">
                <template>插槽内容</template>
            </child>
        </div>
        <script> Vue.component('child', { template: ` <div>
                <p ref="pref1">p1内容</p>
                <slot></slot>
            </div>
 ` }) let vm = new Vue({ el: '#app', }) console.log(vm.$refs.pref) console.log(vm.$refs.child) console.log(vm.$refs.child.$refs.pref1) </script>

结果:

 

持有注册过 ref 特性 的全部 DOM 元素和组件实例。

相关文章
相关标签/搜索