1. props验证与默认值
父props与子props是单向下行绑定:父级的props的值更新会流动到子组件中,但反过来却不行。
避免子组件意外改变父级组件的状态,导致数据流混乱。
每次父级组件发生更新时,子组件中所有的props都将会刷新为最新的值。
不能在子组件内部改变props,否则会导致浏览器控制台发出警告
子组件要修改时,用$emit调用自定义事件,父组件接到后由父组件修改
改变props的常用例子:
这个用来传递一个初始值;这个组件接下来希望将其作为一个本地的数据来使用,要定义一个本地属性用做初始值、
props:['initialCounter'], data:function(){ return{ counter:this.initialCounter } }
这个以一种原始的值传入且需要进行转换,定义一个计算属性
props:['size'], computed:{ normalizedSize:function(){ return this.size.trim().toLowerCase() } }
2. Vue的双向数据绑定
- 定义数据监听器Observer,能够对数据对象所有属性进行监听,数据有变动会获取新值并通知订阅者;
- 定义一个指令解析器Compile,对每个元素节点指令进行扫描,根据指令模板替换数据,以及绑定相应的更新函数;
- 实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图;
Vue实现双向数据绑定主要采用:数据劫持结合“发布-订阅”模式的方式,通过Object.defineproperty()的set和get,在数据变动是发布消息给订阅者触发监听。
Vue组件父传子,子传父,兄弟通信
1. 父传子:(通过props实现)
在父组件中给子组件标签绑定一个属性,属性上挂载需要传递的值;
在子组件通过props[“自定义属性名”]来接受数据;
以下是三种方法,没用vue写,引入vue.js文件,以下是HTML代码:
<body>
<div id="app">
<child></child>
</div>
<script src="./vue.js"></script>//引入vue.js文件
<script>
const child = {
// props: ['msg'], // 第一种方法
inject: ['name', 'age', 'tel'],
template: `
<div>
这是子组件
{{msg}} {{name}} -- {{age}} -- {{tel}}
</div>
`,
data() {
return {
msg: ''
}
},
created() {
// console.log(this.$parent.msg) // 第二种方法 不建议过多的使用
// this.msg = this.$parent.msg
console.log(this.name, this.age, this.tel)
}
}
Vue.component('child', child)
new Vue({
provide: { // 第三种方法 开发高阶组件时建议使用
name: "张三",
age: 16,
tel: 110
},
data:{
msg: '这是要传递给子组件的数据'
}
}).$mount('#app')
</script>
</body>
2. 子传父:(通过$emit实现)
在父组件中给子组件标签绑定一个自定义事件,给这个事件挂载需要调用的方法;
在子组件的方法通过this.$emit(“自定义事件名”)来调用这个方法;
以下是HTML代码:
<body>
<div id="app">
<child @senddata="getData"></child>
</div>
<script src="./vue.js"></script>
<script>
const child = {
template: `
<div>
这是子组件
<button @click="sendData">点击传递数据给父组件</button>
</div>
`,
data() {
return {
msg: '这是要传递给父组件的数据'
}
},
methods: {
sendData() {
this.$emit('senddata', this.msg)
}
}
}
Vue.component('child', child)
new Vue({
data:{
msg: ''
},
mounted() {
console.log(this.$children[0].msg)
},
methods: {
getData(data) {
console.log(data)
}
}
}).$mount('#app')
</script>
</body>
3. 兄弟传参:两种方法
- 通过event bus实现
创建一个空的vue实例eventBUS,作为公共的桥梁;在两个组件中引入创建的bus,组件A用BUS.$ emit(“自定义事件名”,要传递的值)发送数据;组件B用BUS.$on(“自定义事件名”,function(v){挂载从A穿过来的数据})来接受数据
以下是HTML代码:
<body>
<div id="app">
<child1></child1>
<child2></child2>
</div>
<script src="./vue.js"></script>
<script>
const child1 = {
template: `
<div>
这是子组件
<button @click="send">点击传递数据给父组件</button>
</div>
`,
data() {
return {
msg: "这是要传递给父组件的数据",
};
},
methods: {
send() {
this.$bus.$emit("getdata", this.msg);
},
},
};
const child2 = {
template: `
<div>
这是子组件
{{msg}}
</div>
`,
created() {
// console.log(this)
// var _this = this
this.$bus.$on("getdata", (data) => {
// console.log(this)
this.msg = data;
});
},
data() {
return {
msg: "",
};
},
};
Vue.component("child1", child1);
Vue.component("child2", child2);
var bus = new Vue();
Vue.prototype.$bus = bus;
new Vue({
methods: {},
}).$mount("#app");
</script>
</body>
2. 使用vuex来传递
vuex是一个状态管理工具,主要解决中大型复杂项目的数据共享数据
State-存放Vuex store实例的状态对象,用于定义共享的数据。
Action-动作,向store发出调用通知,执行异步操作。
Mutations-修改器,它只用于修改state中定义的状态变量。
getter-读取器,外部程序通过它获取变量的具体值,或者在取值前做一些计算(可以认为是store的计算属性)
modules对state进行分类处理
流程:dispatch到actions,actions是异步操作,从commit到mutations
使用mutations再通过逻辑操作改变state,同步到组件,更新其数据状态。