什么是组件化开发
组件化开发 :一个页面(.vue)可能有一个或多个组件(.vue)组成完整的页面功能。
- 封装的思想,把页面上
可重用的部分封装为组件,从而方便项目的 开发 和 维护。
一个页面, 可以拆分成一个个组件,一个组件就是一个整体, 每个组件可以有自己独立的 结构(template) 样式(style) 和 行为(script) (html, css和js)
vue组件-用scoped实现组件的私有样式
默认组件style 中定义的样式是全局样式,会把其他组件中的标签也设置上样式,存在相同名字覆盖的情况。
解决方案:
局部样式:在style标签上加上[scoped属性]
<stype scoped> //加scoped, 组件内的样式只在当前vue组件生效;相反如果不加,样式就是全局的
h2 {} // h2样式只会在当前组件内生效
</style>
- 在style上加入scoped属性, 就会在此组件的标签上加上一个随机生成的data-v开头的属性。
- 而且必须是当前组件的元素或者子组件的根元素, 才会有这个自定义属性。
vue组件-/deep/深度作用选择符
当父子组件都使用了scoped之后,使用/deep/可以在父组件中控制子组件中的样式。
div /deep/ button{ //在父组件style中,设置button样式加上/deep/,就可以控制子组件button元素的样式
background-color: pink;
}
- 父组件中控制子组件元素或类名,覆盖样式=》需要在前边加上
/deep/。 - 注意⚠️:默认子组件的根元素,会带上父组件的data-v-hash属性,所以可以直接控制。
vue组件通讯_父传子
如果一个组件A在组件B中被导入使用,称组件B是父组件,组件A是子组件。
格式
父组件中:< 子组件 @自定义事件名1="父methods函数1" @自定义事件名2="父methods函数2" />
父传子组件通讯,需要先在父组件中自定义一个动态属性,然后将这个自定义的属性在子组件中使用props属性接收。 父组件:
<template>
<div style="border:1px solid #ccc;margin:5px">
<h1>我是父组件</h1>
<!-- 父传自定义属性 -->
<MyCom :abc='userName' :list="hobby"/>
</div>
</template>
<script>
import MyCom from './MyCom.vue' //导入文件路径
export default {
data(){
//要传送给子组件的数据
return{
userName:'小白',
hobby:['vue','js']
}
},
components:{MyCom} //注册组件
}
</script>
注意:
- 加冒号: 后面是vue变量数据。
- 不加冒号: 后面认为是字符串。 子组件
<template>
<div style="border:1px solid #ccc;margin:5px" >
<h1>我是子组件</h1>
<!-- 使用插值表达式 -->
{{abc}}
<p>{{list[1]}}</p>
<button @click="fn">打印</button>
</div>
</template>
<script>
export default {
props:['abc','list'],//使用props属性接收父组件自定义的属性名
methods: {
fn(){
console.log(this,this.abc); //控制台会打印出小白
}
},
}
</script>
vue单向数据流
在vue中需要遵循单向数据流原则。
- 在父传子的前提下,父组件的数据发生会通知子组件自动更新。
- 子组件内部,不能直接修改父组件传递过来的props => props是只读的。
不要在子组件内部,修改父组件的数据。
说明:父组件传给子组件的是一个对象,子组件修改对象的属性,是不会报错的,对象是引用类型, 互相更新;但不能改变引用地址 props的值不能重新赋值, 但是引用类型可以子改父。
vue组件通信_子传父
子传父是指:从子组件内部把数据传出来给父组件使用或者修改父组件数据
子组件: this.$emit("自定义事件名1", 传值1) ---> 执行父methods里函数代码
父组件
<template>
<div style="border:1px solid #ccc; margin:5px;padding:5px">
<h1>子传父</h1>
添加事件监听
<MyCom @abc="fn"/> 当子组件发生了abc事件要执行fn函数,将数据传送到fn的参数里
<button>改数据</button>
</div>
</template>
<script>
// 导入
import MyCom from './MyCom.vue'
export default {
components: { MyCom },
methods: {
fn(obj){ //参数接收传递来的数据
console.log('fn子组件',obj);
}
},
}
</script>
子组件
<template>
<div style="border:1px solid #ccc; margin:5px;padding:5px">
<h2>子组件</h2>
<button @click="fn">触发abc事件</button> //点击按钮将数据传送到父组件中
</div>
</template>
<script>
export default {
methods: {
fn(){
console.log('子组件click')
// 2. 触发abc事件
this.$emit('abc',{name:'小花'}) //使用$emit属性传数据
}
}
}
</script>
总结
- scoped属性可以实现组件的私有样式。使组件内的样式只在当前vue组件内生效。
- /deep/ 可以在父组件中控制子组件中的样式。
- 父传子语法:
父组件中:< 子组件 @自定义事件名1="父methods函数1" @自定义事件名2="父methods函数2" />
子组件接收:props:['父组件中自定义的事件名','']
props的值不能重新赋值, 但是引用类型可以子改父 - 子传父语法:
子组件: this.$emit("自定义事件名1", 传值1) ---> 执行父methods里函数代码
父组件接收:@自定义事件名="methods函数"里面的参数用来接收传来的数据