1. 属性 & 方法
每个Vue实例都会代理其data对象里的所有属性,且data里必须是函数:
var data = {
a: 1
};
var vm = new Vue({
data: data
});
console.log(vm);
console.log(vm.a === data.a); // true
// 设置属性也会影响到原始数据
vm.a = 2;
console.log(data.a); // 2
// 反之,类双向数据绑定
data.a = 3;
console.log(vm.a); // 3
//Vue实例还暴露了一些有用的实例属性与方法。这些属性与方法都有前缀$, 以便与代理的data属性区分。
var data = { a: 1 }
var vm = new Vue({
el: '#container1',
data: data
})
console.log(vm.$data === data) // true
console.log(vm.$el === document.getElementById('container1')) // true
data.a = 5;
// $watch 是一个实例方法
vm.$watch('a', function (newVal, oldVal) {
// 这个回调将在 `vm.a` 改变后调用
console.log(newVal);
console.log(oldVal);
})
三个组件共享了同一个 data , 因此增加一个 counter 会影响所有组件。但我们可以通过为每个组件返回全新的 data 对象来解决这个问题:
<!DOCTYPE html>
<html>
<body>
<head>
<title>data函数</title>
</head>
<div id="container1">
<component1></component1>
<component1></component1>
<component1></component1>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
var data = { counter: 0 };
// 全局注册
Vue.component('component1', {
template: '<button v-on:click="counter += 1">{{ counter }}</button>',
// data是一个函数,vue不会报错,我们返回给每个组件的实列引用了不同的data对象
data: function() {
return {
counter: 0
}
}
});
new Vue({
el: '#container1'
})
</script>
</html>
2. 父子组件通讯
父组件通过props向下传递数据给子组件:
(注:camelCased(驼峰式) 命名的prop需要转换为相对应的 kebab-case(短横线隔开式)属性命名)
<!DOCTYPE html>
<html>
<body>
<head>
<title>props</title>
</head>
<div id="container1">
<child my-message="hello!"></child>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
// 全局注册
Vue.component('child', {
// 暴露声明props
props: ['myMessage'],
template: '<span>{{ myMessage}}</span>'
});
new Vue({
el: '#container1'
})
</script>
</html>
子组件通过自定义事件给父组件发送消息:
1. 使用 v-on(eventName)监听事件
2.使用 $emit(eventName) 触发事件
<!DOCTYPE html>
<html>
<body>
<head>
<title>$emit</title>
</head>
<div id="container1">
<p> {{ total }} </p>
// v-on:increment
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
// 子组件声明
Vue.component('button-counter', {
template: '<button v-on:click="increment">{{ counter }}</button>',
data: function() {
return {
counter: 0
}
},
methods: {
increment: function() {
this.counter += 1;
// $emit将子组件的方法暴露给父亲v-on绑定的属性
this.$emit('increment');
}
},
})
// 父组件
new Vue({
el: '#container1',
data: {
total: 0
},
methods: {
incrementTotal: function() {
this.total += 1;
}
}
})
</script>
</html>
3. 动态组件
通过使用保留的component元素,动态地绑定到它的 is 特性,我们可以让多个组件使用同一个挂载点,并动态的切换。
keep-alive: 如果把切换出去的组件留在内存中,可以保留它的状态或避免重新渲染,减少性消耗, 为此我们可以添加一个 keep-alive指令参数。
ps: 这里学习一下 Vue 中的 is 的特性,比如有些固定的元素结构<ul><li></li></ul>
, 而不能<ul><component></ul>
, 这个时候为了达到目的可以:
<ul>
<li is="your-component"></li>
</ul>
<!DOCTYPE html>
<html>
<body>
<head>
<title>动态组件</title>
</head>
<template id="tab-01">
<div>这是tab1</div>
</template>
<template id='tab-02'>
<div>这是tab2</div>
</template>
<div id="container1">
<!-- 导航栏 -->
<ul>
<li>
<a href="javascript:void(0)" @click="toggleTabs(tab01Text);">{{ tab01Text }}</a>
</li>
<li>
<a href="javascript:void(0)" @click="toggleTabs(tab02Text);">{{ tab02Text }}</a>
</li>
</ul>
<!-- /导航栏 -->
<!-- 点击导航后要切换的内容 -->
<div class='content' style='height: 200px'>
<!-- 如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令参数 -->
<keep-alive>
<component :is="currentView"></component>
</keep-alive>
</div>
<!-- /点击导航后要切换的内容 -->
</div>
</body>
<script src="./vue.js"></script>
<script type="text/javascript">
var tab01 = Vue.extend({
template: '#tab-01'
});
var tab02 = Vue.extend({
template: '#tab-02'
});
// 新建vue实例
var newVue = new Vue({
el: '#container1',
data: {
tab01Text: "tab01", // 菜单一
tab02Text: "tab02", // 菜单二
currentView: "tab01" // 默认选中的导航栏
},
// 局部注册组件
components: {
tab01: tab01,
tab02: tab02,
},
methods: {
// 绑定tab的切换事件
toggleTabs: function(tabText) {
this.currentView = tabText;
}
}
})
</script>
</html>