Vue的组件传值技巧

接着上篇文章,我们来讲解一下,Vue组件传值的奇淫巧技。

Vue中父直接传递方法给子组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>

<div id="app">
    <ul>
        <!--定义一个c-school的属性,并将父组件中的方法传递给它-->
        <school v-for="(item,index) in schools" :school-name="item" :c-school="cSchool"></school>
    </ul>
    <hr/>
    选择的学校:<p>{{chooseSchoolName}}</p>
</div>
</body>
</html>

<script>

    //Vue中全局注册:组件,即:注册后,在Vue的实例中都能使用
    Vue.component('school', {
        props: ['schoolName','cSchool'],
        template: `
            <li>
                <span>{{schoolName}}</span>
                <button @click="chooseSchool(schoolName)">选择</button>
            </li>
        `,
        methods: {
            chooseSchool: function (schoolName) {
                console.log(schoolName)
                //this.$emit('choose-name',schoolName)

                console.log(this.cSchool)
                // 直接调用父组件中的方法
                this.cSchool(schoolName)
            }
        }
    })
    let app = new Vue({
        el: '#app',
        data: {
            schools: ['清华', '北大', '复旦', '上交'],
            chooseSchoolName:''
        },
        methods: {
            cSchool:function (data) {
                console.log("data:"+data)
                this.chooseSchoolName = data
            }
        }
    })
</script>

大家,仔细琢磨即可,父组件直接传递给组件自己的方法,然后子组件调用该方法修改了父组件中的data值。


this.$parent

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>

<div id="app">
    <ul>
        <school v-for="(item,index) in schools" :school-name="item"></school>
    </ul>
    <hr/>
    选择的学校:<p>{{chooseSchoolName}}</p>
</div>
</body>
</html>

<script>

    //Vue中全局注册:组件,即:注册后,在Vue的实例中都能使用
    Vue.component('school', {
        props: ['schoolName','cSchool'],
        template: `
            <li>
                <span>{{schoolName}}</span>
                <button @click="chooseSchool(schoolName)">选择</button>
            </li>
        `,
        methods: {
            chooseSchool: function (schoolName) {
                console.log(schoolName)
                //this.$emit('choose-name',schoolName)

                console.log(this)
                console.log(this.$parent)
            }
        }
    })
    let app = new Vue({
        el: '#app',
        data: {
            schools: ['清华', '北大', '复旦', '上交'],
            chooseSchoolName:''
        },
        methods: {
            cSchool:function (data) {
                console.log("data:"+data)
                this.chooseSchoolName = data
            }
        }
    })
</script>

在子组件中的this中,我们看到了可以获取到一个特殊的对象,$parent,该对象指代的就是该子组件的直接父组件,即这里的app组件。

因此,我们可以使用这个对象来调用父组件中的方法:

方法一

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>

<div id="app">
    <ul>
        <school v-for="(item,index) in schools" :school-name="item"></school>
    </ul>
    <hr/>
    选择的学校:<p>{{chooseSchoolName}}</p>
</div>
</body>
</html>

<script>

    //Vue中全局注册:组件,即:注册后,在Vue的实例中都能使用
    Vue.component('school', {
        props: ['schoolName','cSchool'],
        template: `
            <li>
                <span>{{schoolName}}</span>
                <button @click="chooseSchool(schoolName)">选择</button>
            </li>
        `,
        methods: {
            chooseSchool: function (schoolName) {
                console.log(schoolName)
                //this.$emit('choose-name',schoolName)

                console.log(this)
                console.log(this.$parent)

                //直接调用父组件的方法
                this.$parent.cSchool(schoolName)
            }
        }
    })
    let app = new Vue({
        el: '#app',
        data: {
            schools: ['清华', '北大', '复旦', '上交'],
            chooseSchoolName:''
        },
        methods: {
            cSchool:function (data) {
                console.log("data:"+data)
                this.chooseSchoolName = data
            }
        }
    })
</script>

方法二

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>

<div id="app">
    <ul>
        <school v-for="(item,index) in schools" :school-name="item"></school>
    </ul>
    <hr/>
    选择的学校:<p>{{chooseSchoolName}}</p>
</div>
</body>
</html>

<script>

    //Vue中全局注册:组件,即:注册后,在Vue的实例中都能使用
    Vue.component('school', {
        props: ['schoolName','cSchool'],
        template: `
            <li>
                <span>{{schoolName}}</span>
                <button @click="$parent.cSchool(schoolName)">选择</button>
            </li>
        `,
        methods: {
            chooseSchool: function (schoolName) {
                // console.log(schoolName)
                // //this.$emit('choose-name',schoolName)
                //
                // console.log(this)
                // console.log(this.$parent)
                //
                // //直接调用父组件的方法
                // this.$parent.cSchool(schoolName)
            }
        }
    })
    let app = new Vue({
        el: '#app',
        data: {
            schools: ['清华', '北大', '复旦', '上交'],
            chooseSchoolName:''
        },
        methods: {
            cSchool:function (data) {
                console.log("data:"+data)
                this.chooseSchoolName = data
            }
        }
    })
</script>

this.$root

组件是可以嵌套多层的,如果想要调用父组件的父组件的父组件就会写很长的表达式:this.$parent.$parent.$parent

因此,vue提供了一个this.$root对象,可以直接获取到根对象,在我们这里根对象就是:app。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>

<div id="app">
    <ul>
        <school v-for="(item,index) in schools" :school-name="item"></school>
    </ul>
    <hr/>
    选择的学校:<p>{{chooseSchoolName}}</p>
</div>
</body>
</html>

<script>

    //Vue中全局注册:组件,即:注册后,在Vue的实例中都能使用
    Vue.component('school', {
        props: ['schoolName','cSchool'],
        template: `
            <li>
                <span>{{schoolName}}</span>
                <button @click="$root.cSchool(schoolName)">选择</button>
            </li>
        `,
        methods: {
            chooseSchool: function (schoolName) {
                // console.log(schoolName)
                // //this.$emit('choose-name',schoolName)
                //
                // console.log(this)
                // console.log(this.$parent)
                //
                // //直接调用父组件的方法
                // this.$parent.cSchool(schoolName)
            }
        }
    })
    let app = new Vue({
        el: '#app',
        data: {
            schools: ['清华', '北大', '复旦', '上交'],
            chooseSchoolName:''
        },
        methods: {
            cSchool:function (data) {
                console.log("data:"+data)
                this.chooseSchoolName = data
            }
        }
    })
</script>

通过上图,使用this.$root对象来调用方法也能成功。

this.$children

父组件可以直接修改this.$children来控制子组件中的数据。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>

<div id="app">
    <ul>
        <school v-for="(item,index) in schools" :school-name="item"></school>
    </ul>
    <hr/>
    选择的学校:<p>{{chooseSchoolName}}</p>
</div>
</body>
</html>

<script>

    //Vue中全局注册:组件,即:注册后,在Vue的实例中都能使用
    Vue.component('school', {
        props: ['schoolName','cSchool'],
        template: `
            <li>
                <span>{{schoolName}}</span>
                <button @click="$root.cSchool(schoolName)">选择</button>
            </li>
        `,
        methods: {
            chooseSchool: function (schoolName) {
                // console.log(schoolName)
                // //this.$emit('choose-name',schoolName)
                //
                // console.log(this)
                // console.log(this.$parent)
                //
                // //直接调用父组件的方法
                // this.$parent.cSchool(schoolName)
            }
        }
    })
    let app = new Vue({
        el: '#app',
        data: {
            schools: ['清华', '北大', '复旦', '上交'],
            chooseSchoolName:''
        },
        methods: {
            cSchool:function (data) {
                console.log("data:"+data)
                this.chooseSchoolName = data

                console.log(this)
                console.log(this.$children)
            }
        }
    })
</script>

说明

一般,我们不使用这样的方法来控制父子组件之间的传值,因为这样不利于维护,大家都直接调用方法控制数据,强耦合,最好还是使用上一节介绍的方法,也是官方提供的方法。


  目录