组件
含义 可以复用的ui模块 ,一个组件对应一个实例(new Vue)
- 组件化开发
- 概念 将一个完整的页面抽离成一个个独立的组件=>组件是可复用的
Vue实例 - 优势 复用率高
- 概念 将一个完整的页面抽离成一个个独立的组件=>组件是可复用的
1 注册组件
-
1.1全局注册
.... <div id="app"> //插入组件 <组件名></组件名> </div> .... //参数一:组件的名称 //参数二:配置对象 Vue.component('组件名',{ //template下只能有一个根元素 template:'<h1>我是待渲染的模板</h1>' }) -
1.2局部注册
.... <div id="app"> //插入组件 <组件名></组件名> </div> .... var vm=new Vue({ el:'#app', components:{ 组件名(){ template:'<h1>我是待渲染的模板</h1>', } } }) -
组件注册的注意点
- 全局组件注册一定要在
vue实例之前 - 不管在何种情况下
template只能有一个根节点 - 组件里的配置项和
vue实例中的配置项几乎是一样的 - 组件中的
data是一个方法,并且必须要有返回值
- 全局组件注册一定要在
为啥组件中的data是一个方法,而不是一个对象了?
- 组件是一个可复用的实例
- 组件是拿来复用的,但是,组件内的数据,是不可以共享的
- 如果data是对象,在某个实例修改了数据,其他所有实例也会受到影响
- data是一个函数的话,修改数据就只会影响当前实例
2组件的通讯(面试)
组件是一个独立封闭的个体
组件之间不能直接访问数据,可以通过组件的通讯来实现数据的访问
2.1父组件传值给子组件(父传子)
- **第一步:**通过自定义属性将父组件的数据传给子组件
- **第二步:**在子组件通过props配置项指定一下要接收的数据
- props是一个数组,props中的数据是只读的
<div id='app'>
//第一步
<child :msg='pmsg'></child>
</div>
//子组件
Vue.component("child",{
template:`<div>子组件的值:{{msg}}</div>`,
//第二步
props:[`msg`]
})
//父组件
const vm=new Vue({
el:'#app',
data:{
pmsg:'哈哈'
}
})
2.2子组件传值给父组件(子传父)
- 第一步 在父组件中准备一个方法
- 第二步,通过自定义事件将方法传递给子组件
- 第三步 子组件调用传过来的方法(调用的时候可以传参)
<div id='app'>
//第二步,通过自定义事件将方法传递给子组件
<child @fn="pfn"></child>
</div>
//子组件
Vue.component("child",{
template:`<div>子组件的值:{{msg}}</div>`,
props:[`msg`],
data(){
return{
cmsg:'子组件的数据'
}
},
created(){
//第三步 子组件调用传过来的方法
this.$emit('fn',this.cmsg)
}
})
//父组件
const vm=new Vue({
el:'#app',
methods:{
// 第一步 在父组件中准备一个方法
pfn(data){
console.log("子组件里的数据是",data)
}
}
})
2.3非父子之间的数据传递
- 非父子之间的通讯是通过
event bus公交车(事件总线)的机制来实现的 - 事件总线实际上就是一个空的vue实例,事件总线可以实现任意两个组件之间的通讯,并不在意这两个组件是什么样的层级关系
- 事件总线的过程
- 第一步:事件总线(创建一个新的
vue实例)=>var bus = new Vue() - 第二步:发送数据,可在点击事件里触发事件=>
bus.$emit("事件名","要传递的数据") - 第三步:接收数据 在
created钩子函数中注册事件=>bus.$on('事件名', 接收数据的参数 => {})
- 第一步:事件总线(创建一个新的
<div id="app">
<jack></jack>
<rose></rose>
<div>
......
// 第一步 : 事件总线
var bus = new Vue()
Vue.component('jack',{
template:`
<div @click='send'>我是jack</div>
`,
methods:{
send(){
// 第二步 : 发送数据 可在点击事件里 触发事件
// 参数1 : 唯一标识 参数2:参数
bus.$emit("love","You jump")
}
}
})
Vue.component('rose',{
template:`
<div>我是rose</div>
`,
created(){
// 第三步 : 接收数据 可在 created 里 注册事件
bus.$on('love', arg => {
console.log('接收过来的', arg)
})
}
})
3其他
3.1vue中存储属性的地方
-
**data:**可读可写,在子组件中是一个方法
-
**计算属性 (computed):**根据data中的数据变化自动计算发生改变
-
props
-
只读
-
不区分大小写
- 官 : HTML 中的特性名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。
html 的标签和 属性 都是一样,忽略大小写
<H1 TITLE="哈哈">我是h1</H1>- 官 : 这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名不好使了
<child :cMsg="pmsg"></child>会报警告,父传子也接收不到了- 原因是 : 接收的属性是:cMsg, 接收的数据名,因为忽略大小写,数据已为 : cmsg
- 所以已经准备要读取的 是 cmsg 的值,找不到,所以要报警告
You should probably use "c-msg" instead of "cMsg".
- 方式 1 : 全用小写,不要使用驼峰命名
接收 :
cmsgprops/读取 :cmsg- 方式 2 官 : 需要使用其等价的 kebab-case (短横线分隔命名) 命名:
接收 :
:c-msg='pmsg'props/读取 :cMsg
-
3.2单向数据流(组件与组件之间)
所有的 prop 都使得其父子 prop 之间形成了一个
单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。