简体   繁体   中英

Why can't I access props within my component?

I've copied the Grid Component Example into a single-file component ( Grid.vue ). Within that component, I'm not able to access the columns prop. console.log(this.columns) always prints: [__ob__: Observer] to the log. Can someone tell me why? This works fine in their example on the page and in JSFiddle .

Here's my Grid.vue file:

<script>
    export default {
        name: 'grid',
        
        props: {
            data: Array,
            columns: Array,
            filterKey: String
        },
        data: function() {
            var sortOrders = {}
            console.log(this.columns)
            this.columns.forEach((column) => {
                sortOrders[column] = 1
            });
            return {
                sortCol: '',
                sortOrders: sortOrders
            }
        },
        computed: {
            filteredData: function () {
                var sortCol = this.sortCol
                var filterKey = this.filterKey && this.filterKey.toLowerCase()
                var order = this.sortOrders[sortCol] || 1
                var data = this.data
                if (filterKey) {
                    data = data.filter((row) => {
                        return Object.keys(row).some((key) => {
                            return String(row[key]).toLowerCase().indexOf(filterKey) > -1
                        })
                    })
                }
                if (sortCol) {
                    data = data.slice().sort((a, b) => {
                        a = a[sortCol]
                        b = b[sortCol]
                        return (a === b ? 0 : a > b ? 1 : -1) * order
                    })
                }
                return data
            }
        },
        filters: {
            capitalize: function (str) {
                return str.charAt(0).toUpperCase() + str.slice(1)
            }
        },
        methods: {
            sortBy: function (key) {
                this.sortCol = key
                console.log(this.sortOrders[key])
                this.sortOrders[key] = this.sortOrders[key] * -1
                console.log(this.sortOrders[key])
            }
        },
        created() {
            
        },
        mounted() {
            // var app = this
        },
    }
</script>

I'm using this component within another component like so:

<template>
    <div>
        <form id="search">
            Search <input name="query" v-model="searchQuery">
        </form>
        <grid :data="things" :columns="thingColumns" :filterKey="searchQuery"></grid>
    </div>
</template>

<script>
    import Grid from './Grid.vue';

    export default {
        name: 'things-grid',
        
        data: function() {
            return {
                things: [],
                thingColumns: [],
                searchQuery: ''
            }
        },
        mounted() {
            var app = this

            app.things = [
                {id: 1, this: 'this 1', that: 'that 1', thing: 'thing 1'},
                {id: 2, this: 'this 2', that: 'that 2', thing: 'thing 2'},
                {id: 3, this: 'this 3', that: 'that 3', thing: 'thing 3'},
                {id: 4, this: 'this 4', that: 'that 4', thing: 'thing 4'},
                {id: 5, this: 'this 5', that: 'that 5', thing: 'thing 5'},
            ]

            app.thingColumns = [
                'this', 'that', 'thing'
            ]

            app.searchQuery = ''


        },
        components: { Grid }
    }
</script>

In:

<grid :data="things" :columns="thingColumns" :filterKey="searchQuery"></grid>

The value of this.thingColumns is passed as :columns when mounting.

Thus, the console.log(this.columns) inside Grid.vue/data() prints when it is mounting .

And when it is mounting, thingColumns is empty in the parent:

data: function() {
    return {
        things: [],
        thingColumns: [],              // initially empty
        searchQuery: ''
    }
},
mounted() {
    var app = this
    // ...
    app.thingColumns = [               // this code only runs after it is mounted
        'this', 'that', 'thing'
    ]
    // ...
},

Since the console.log(this.columns) inside Grid.vue/data() prints when it is mounting, that is, before it is mounted , it prints an empty array:

[__ob__: Observer]  // this is an empty array, the __ob__ thing is related to Vue internals

Because, well, parent's thingColumns will only have data after the mounted() hook executes.

And since it is a reactive array, when you update it, it will update the child grid component as well.


Solution:

Move the property initalization code from mounted() to created() :

created() {                            // was mounted()
    var app = this
    // ...
    app.thingColumns = [
        'this', 'that', 'thing'
    ]
    // ...
},

This will initialize the data sooner and make it available in time for the console.log() in the child to pick it up.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM