zoukankan      html  css  js  c++  java
  • Vue组件传值、refs、插槽

    一、组件传值

    1.父组件向子组件传值

    因为子组件本身不能拿到父组件的data数据来用,所以在子组件里用props接收,props是一个数组

    父组件向子组件传值
    <div id="app">
        <com1 :parent="msg" :parentarr="arr"></com1>
    </div>
    <template id="com">
        <div>
            {{parent}}
            <ul>
                <li v-for="i in parentarr">{{i}}</li>
            </ul>
        </div>
    </template>
    <script src="lib/vue-2.4.0.js"></script>
    <script type="text/javascript">            
    var vm=new Vue({
        el:"#app",
        data:{
            msg:"父组件的msg",
            arr:[1,2,3],
        },
        components:{
            com1:{
                template:"#com",
                props:["parent",'parentarr'],//父组件向子组件传值,用props    
            }
        }
    })
    </script>

    2.子组件向父组件传值

    子组件不能直接使用父组件的data和methods,子组件向父组件传值用 @和$emit实现(通过函数的形式传出,在父组件接收)

    做法:

    在父组件里定义一个@xxx="xxx2"的方法,父组件把方法传递给子组件,this.$emit()的第一个参数和xxx的名称一样,父元素的方法xxx2传一个实参进去就相当于是当前传回来的值

    this.$emit("fun1",this.xxx) 方法名字/要传出的值

    子组件向父组件传值
    <div id="app1">
        <com-name @fun1="getData"></com-name>
    </div>
    
    <template id="com2">
        <div>
            <button @click="getsonData">调用父组件的getdata</button>
        </div>
    </template>
    <script src="lib/vue-2.4.0.js"></script>
    <script type="text/javascript">
    var vm=new Vue({
        el:"#app1",
        data:{
            fromson:""
        },
        methods:{
            getData(x){//传实参
                console.log("父元素的方法getdata拿到子组件里的数据是==="+x)
                this.fromson=x;
            }
        },
        components:{
            comName:{
                template:"#com2",
                data(){
                    return {
                        sonmsg:"子组件里的msg"
                    }
                },
                methods:{
                    getsonData(){
                        this.$emit("fun1",this.sonmsg)//$emit调用fun1
                    }
                }
            },
            
        }
    })
    </script>

    二、refs获取dom节点

    Vue不提倡用原生的dom操作获取节点,它封装了自己的方法来实现获取dom

    做法:

    给要获取的dom一个ref属性,起一个名字,通过this.$refs来得到组件里所有有ref属性的dom节点,返回的是一个json

    <div id="app">
       <p ref="p1">父组件里的p</p>
       <button @click="getCon">获取内容</button>
       <com ref="login"></com>
    </div>
    <template id="login">
        <div>
            <p>{{sonmsg}}</p>
        </div>
    </template>
    <script src="lib/vue.js"></script>
    <script>
        Vue.component("com",{
            template:"#login",
            data(){
                return {
                    sonmsg:"子组件的msg"
                }
            },
        })
        var vm=new Vue({
            el:"#app",
            methods:{
                getCon(){
                    console.log(this.$refs.login.sonmsg)//子组件的msg
                    console.log(this.$refs.p1.innerHTML)//父组件里的p
                }
            }
        })
    </script>

    那么,子组件向父组件传值就有俩种方法

    ①用@和$emit

    ②组件也可以有ref属性,可以通过组件的ref属性拿到子组件的data和method

    三、插槽 (slot)   可以更好的去复用组件

    插槽是将父组件中的子组件模板数据正常显示出来

    假设组件的名称为child

    1.插槽的概念

    child组件开标签和闭标签之间的内容正常不会显示在页面中,如果想要让他显示,用slot标签代表这些内容,想要让她在哪儿显示就放在模板的哪个位置

    理解插槽:

    组件就相当于是封装的html 那么插槽就相当于是封装函数里的参数,是每次调用时候都可以赋不同的值的东西

    2.具名插槽(传递name属性)

    给放在child开标签和闭标签之间的模板或者组件加上v-slot:自定义名字  的指令,在用的时候使用slot标签,在子组件中的 <slot><slot> 里面添加 name='自定义名字' ,通过name属性选择调用哪个插槽。如果父组件中有一部分没有添加 slot 属性,则此处就是默认的插槽,在子组件中的slot直接就是使用的父组件的默认插槽部分

    总:在<template>元素上使用v-slot:自定义名字 指令

    <template v-slot:header>
        <div>AAA</div>
    </template>
    
    <header>
        <slot name="header"></slot>
    </header>

    v-slot 只能添加在<template>上,v-slot的缩写#

    <template #header>
        <div>AAA</div>
    </template>

    3.后备内容

    在<slot></slot>标签中的内容将在没有匹配到插槽内容时渲染

    4.作用域插槽 (让插槽内容可以访问到子组件中的数据)

    插槽虽然是属于这个组件的,但是因为他没有放在组件的模板里,所以不能直接使用组件的data数据,如果要想使用组件的data 应该用属性传值的方法把数据传过去 在插槽里通过v-slot:xx="" 等号后面的值接收数据,接收到的数据是一个json 因为有可能传过来不只一个值

    v-slot:xx="yy"  xx代表插槽的名字 yy代表接收到组件的data数据

    <div id="app">
        <child>
            <template   v-slot:head="datas">
                <div>
                    <h5>组件child里的头部模板=={{datas.textcon}}</h5>
                </div>
            </template>
            
            <template v-slot:foot>    
                <div>
                    <h5>组件child里的尾部模板</h5>
                </div>
            </template>
    
            <template>
                <div>我是一个没有名字的插槽</div>
            </template>
        </child>
    
        <child>
            <template v-slot:head>
                <div>
                    <h4>第二次调用组件child的头部模板</h4>
                </div>
            </template>
            <template v-slot:foot>
                <div>
                    <h4>第二次调用组件child的的尾部模板</h4>
                </div>
            </template>
        </child>
    
    </div>
    <template id="login">
        <div>
            <header>
                <slot name="head" :textcon="text" ></slot>
            </header>
            <p>{{text}}</p>
            <slot>AA</slot>
            <!-- 后备内容放在slot标签里,如果插槽没有传过来内容的话 默认显示AA,如果传过来内容就取代AA -->
            <footer>
                <slot name="foot"></slot>
            </footer>
        </div>
    </template>
    <script src="lib/vue.js"></script>
    <script>
        Vue.component("child", {
            template: "#login",
            data() {
                return {
                    text: "子组件的内容",
                }
            },
        })
    
        var vm = new Vue({
            el: "#app",
        })
    </script>
  • 相关阅读:
    字符串_操作
    Error: Cannot find module 'webpack-cli/bin/config-yargs'
    ElementUI-Table 表头无法编辑问题
    ElementUI-Cascader组件同时支持懒加载和选择任意一级 问题踩坑
    vue强制刷新子组件
    footer部分,当页面主题内容不满一屏时,始终位于页面底部
    未知宽高的元素水平垂直居中方法总结
    fix元素居中
    link和@import引入css的区别
    Jquery拓展方法
  • 原文地址:https://www.cnblogs.com/zhd09/p/11750530.html
Copyright © 2011-2022 走看看