JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<div id="demo">
    <test todo="{{todo}}">
		<table class="table">

			<!-- table head --> 
			<thead>
				<tr>
					<th></th>
					<th v-if="todo.columns[0].display">{{todo.columns[0].name}}</th>
                    <th v-if="todo.columns[1].display">{{todo.columns[1].name}}</th>
				</tr>
			</thead>

			<!-- table body --> 
			<tbody>
				<tr v-repeat="item in todo.data">
					<td><input type="checkbox" v-model="item.selected"></td>
					<td v-if="todo.columns[0].display">{{item.title}}</td>
                    <td v-if="todo.columns[1].display">{{item.description}}</td>
				</tr>
			</tbody>

		</table>
	</test>
</div>

<!-- Templates -->
<script type="text/x-template" id="test-template">
    <div>
        This table is within a "content" element and has {{todo.totalColumns}} columns.
        <content></content>
    </div>
</script>

JavaScript

Vue.config.debug = true;
new Vue({ 
    el: '#demo',
	data: {
    	todo: {
            totalColumns: 0,
            data: [],
            // this throws vue errors in console
            columns: []
            // this works
            // columns: [{name: 'Title', display: true}, {name: 'Description', display: false}]
        }
    },
    ready: function(){
        
        // simulate ajax response
      	setTimeout(function(){  
            this.todo.columns.$set(0,{name: 'Title', display: true});
            this.todo.columns.$set(1,{name: 'Description', display: true});
            
            this.todo.data = [{title: 'Kris', description:"foo"}, {title: 'Bob', description: "bar"}];
            this.todo.totalColumns = this.todo.columns.length;
        }.bind(this), 100);
    },
    components: {
    	'test': {
            props: {
                todo: {
                    type: Object
                }
            },
        	template: '#test-template'
        }
    }
});