• Vue插槽、ref和$refs用法


    1.vue插槽

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

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

    (1)不带插槽的情况:

            <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>

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

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

            <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.编译作用域

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

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

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

            <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>

    结果:

     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 元素和组件实例。

  • 相关阅读:
    线程安全与可重入编写方法
    新手MySQL工程师必备命令速查手册
    分布式之数据库和缓存双写一致性方案解析
    在java代码中用xslt处理xml文件
    Java并发编程之并发代码设计
    Java多线程和并发基础
    Java多线程面试大全
    springboot获取URL请求参数的多种方式
    JAVA文件转换为Base64
    Silver Cow Party
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/12106565.html
Copyright © 2020-2023  润新知