父向子传值
通过标签属性传值
如果子组件的props接收了 那这个标签属性就具有props特性
如果子组件的props没有接收 那这个标签属性就是一个普通的自定义属性
父组件如何向子组件传值
父组件通过标签属性的形式向子组件传值。
子组件可以通过props属性正常接收到来自父组件的值。
但值得注意的是 子组件接收到父组件的值后不应该修改接收到的值,
因为该值果然是一个对象,而且被几个子组件共同引用着。那很有可能会导致脏数据
非得改这数据,应该怎么办?
转存一份,再改
在vue中组件间传值是要单向数据流的,子组件不能随意修改来着父组件的值。
<body>
<div id="app">
<v-count class="count" :count="count"></v-count>
<v-count class="count" :count="count"></v-count>
</div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script src="../../js/vue.js"></script>
<script>
Vue.config.productionTip=false;
new Vue({
el:"#app",
data:{
count:{
flag:0
}
},
components:{
"v-count":{
props:["count"],
data(){
return {
//转存!!! 不是存地址值!! 而是存实际的数据!!!
// myCount:JSON.parse(JSON.stringify(this.count))
myCount:_.cloneDeep(this.count) //引入第三方库来深度复制
}
},
template:`<span @click="add">{{myCount.flag}}</span>`,
methods:{
add(){
//子組件直接修改了父组件的数据 不可取!!!
//在大型项目中 会造成代码难以维护!
this.myCount.flag++
}
}
}
}
})
</script>
props
props特性
最终不会表现在dom节点中
子组件拿到props之后就等于是拿到了一个data
非props特性
会表现在dom节点中
props验证:
我们可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,
则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助
验证方式:
props:[] 数组;数组的每一项表示接受父组件传过来的哪些属性(无法做验证)
props:{} 对象;通过键值对的形式表示接受父组件传过来的哪些属性
key :哪些属性
value:验证规则
key:type
key:[type1,type2]
key:{
type: String,
required: true,
//default: 100
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
//自定义验证
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
type: String Number Boolean Array Object Date Function Symbol
子向父传值
1.子组件通过触发一个方法(该方法触发的是vue自定义事件)
2. 通过vue自定义事件
<body>
<div id="app">
<v-count class="count" :count="count" @add="add"></v-count>
<v-count class="count" :count="count" @add="add"></v-count>
</div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script src="../../js/vue.js"></script>
<script>
Vue.config.productionTip=false;
new Vue({
el:"#app",
data:{
count:{flag:0}
},
methods:{
add({name,step}){
if(name==="v-count"){
this.count.flag+=step
}
}
},
components:{
"v-count":{
props:["count"],
template:`<span @click="add">{{count.flag}}</span>`,
methods:{
add(){
//子向父的数据传递(通过vue自定义事件)
this.$emit("add",{name:"v-count",step:2})
}
}
}
}
})
</script>
非父子
总线机制(on是绑定(接收值),emit是执行(给值))
<body>
<div id="app">
<v-a></v-a>
<v-b></v-b>
</div>
</body>
<script src="../../js/vue.js"></script>
<script>
//Object.create 实现对象级别的继承
//vue源码: VueComponent.prototype = Object.create(Vue.prototype)
// VueComponent.prototype.__proto__ = Vue.prototype
// 对象的隐式原型 指向其构造函数的 显示原型
// 原型链: 隐式原型链
/*vue组件的原型链:
vue组件.__proto__
VueComponent.prototype.__proto__
Vue.prototype.__proto__
Object.prototype.__proto__
null*/
Vue.config.productionTip=false;
Vue.prototype.$bus=new Vue()
new Vue({
el:"#app",
components:{
"v-a":{
template:`<span @click="clickFn">v-a组件</span>`,
data(){
return {
msg:"msg from v-a"
}
},
methods:{
clickFn(){
//第一个参数时需要执行的on的事件名,第二个参数是传递的参数
this.$bus.$emit("msg",this.msg)
}
}
},
"v-b":{
template:`<span>{{msg}}</span>`,
data(){
return {
msg:"v-b组件"
}
},
mounted(){
//this.$bus.$emit("msg")
//第一个参数是名称(emit时需要),第二个参数时回调函数(让这个组件的msg等于传过来的msg)
this.$bus.$on("msg",(msg)=>{
this.msg = msg
})
}
}
}
})
pubsub