组件的基础
# 组件基础
## 什么是组件
>对我们的页面中的共用的元素,进行拆分,单独做成一个模块,方便后续的使用,这个模块,我们就可以叫做 组件。
组件也是我们vue中一大特色。借鉴 react
-组件的定义(全局注册)
-data 必须是一个函数
-单个根元素
## 组件的使用
>将组件的名称,当作是一个 自定义的 html 元素来使用
1.当我们注册好**全局组件**,这个组件就可以在整个项目中的 new Vue 根实例dom上或者其余的组件上来使用
# Prop (传参)
>prop 是我们组件上需要的特性。可以由调用组件的地方传递下来。
1.在组件内部,使用 props 选项来定义好,我这个组件需要那些 “参数”。
2.调用组件的时候,在组件的标签上面,通过自定义的属性来写prop
# 自定义事件
# 组件上使用 v-model
# 插槽 slot 内容分发
# 动态组件
-解析 DOM 模板时的注意事项
## PS:
1.组件的名字不要与现有标签重名。
2.组件的 template 需要有 根元素,不能直接写 文本。
3.组件的 data 必须是一个 函数,在函数里面 return 一个对象。
4.组件的 template 必须有一个 根元素,且只能有一个根元素。
5.组件的 props 定义的时候,可以是 小写,也可是 驼峰命名的。使用的时候,
直接在 DOM 上是使用:
-小写 msg -> msg
-驼峰 isHun -> is-hun
在template模板里面使用:
-小写 msg -> msg
-驼峰 isHun -> isHun 也可以 is-hun
6.全局注册的组件,必须在 new vue 之前注册。
7.子组件不能修改父组件的数据,只能通过打招呼的形式。自定义事件。
8.props 是不允许修改的。。。。。。。。。。。
9.在我们DOM上面。调用组件的时候,不能直接 自闭合。。XHTML。 但是如果是在模板中template字符串模板中使用的话,就没有这个限制。。。。
# 组件之间的通信
-父 -> 子 prop
-子 -> 父 $emit 参数是通过 $event 接收的 ,如果需要多个参数,那么请做成对象的形式。。。
PS: 层级过深的时候,通信流程会很麻烦。这时有两种解决方法
1.通过 空的 Vue 实例对象。 在某个 绑定事件,在另一个位置 触发事件, 中央事件管理器
2.通过 状态管理器。。。。VUEX
# 在组件中如何使用v-model 并且数据是 props 传递过来的。
1.调用组件的时候,写 v-model .然后需要在 组件里面,使用 value 这个props
2.<base-inputv-model="searchText"/>
3.<inputtype="text":value="value"@input="$emit('input', $event.target.value)"/>
# slot
template 里面某个位置写上<slot></slot>这个就是 vue 中默认给我们提供的一个内置组件。
1.组件的引用
<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<metahttp-equiv="X-UA-Compatible"content="ie=edge">
<title>Document</title>
</head>
<body>
<divid="app">
<!--当成一个开始闭合(建议使用这个,可以重复复用) -->
<li-h></li-h>
<!--自闭和-->
<li-h/>
</div>
</body>
</html>
<scriptsrc="../js/vue.js"></script>
<!--
什么是组件?
把页面中共用的元素进行按照功能拆分,成为一个独立的模块,
方便后续的使用和维护,这个模块我们就可以叫组件
-->
<script>
//注册组件Vue.componet(全局组件)
//Vue.component('组件的名字','组件的选项对象')
Vue.component('li-h', {
// template:自定义的组件的内容
template:`
<div>
<h1>第一个组件,是一个头部组件</h1>
{{ msg }}
</div>
`,
//在组件中data必须是个函数
data () {
return{
//数据返回到data中我们在template中渲染即可
msg:'第一次用全局组件的data'
}
}
})
//实例化Vue项目的根实例
varvm =newVue({
el:'#app',
data: {
}
})
</script>
2.props 传参
<body>
<divid="app">
<!--当成一个开始闭合(建议使用这个,可以重复复用) -->
<li-hnews="在组件中自定义的news属性,通过props接收值,在组件中传值"></li-h>
<!--组件每次复用都是相同的内容,我们可以通过调用不同props来区别组件的内容-->
<li-his-hun="true"></li-h>
</div>
</body>
</html>
<scriptsrc="../js/vue.js"></script>
<script>
//组件不仅仅可以在页面上调用,也可以放在其他组件的template中
Vue.component('li-m',{
template:`
<button>我是li-m的按钮放在li-h的template</button>
`,
})
Vue.component('li-h', {
// props定义参数,需要外部传递值
props: ['news','isHun'],//在模板里就插值调用{{ news }}
//在方法里就this.news使用
//组件模板
template:`
<div>
<h1>第一个组件,是一个头部组件</h1>
{{ msg }}
<p>{{ news }}</p>
<button v-if="isHun">未婚</button>
<li-m></li-m>
</div>
`,
data () {
return{
msg:'第一次用全局组件的data'
}
}
})
varvm =newVue({
el:'#app',
data: {
}
})
</script>
2.自定义事件
<body>
<divid="app">
<l-pv-for="(item,index) in childs"
:key="index":name="item"@yyy='fn1'></l-p>
</div>
</body>
</html>
<scriptsrc="../js/vue.js"></script>
<script>
// new出一个空的Vue实例
varbus =newVue();//可以称为中央事件管理器
Vue.component('l-e',{
template:`
<div>
<p>我是儿子组件</p>
<button @click='fn1'>我要给父元素改名字</button>
</div>
`,
methods: {
fn1(){
//子元素组件不能直接修改父组件的数据,会影响数据流
//采用自定义事件
//就是在父组件上,使用我的时候,自定义一个事件
// $emit('事件的名字')//调用自定义事件
console.log('我是儿子组件的fn1,我要改变父元素');
this.$emit('xxxxx');
}
}
})
Vue.component('l-p',{
// prop,传参,父传子
props: ['name'],
template:`
<div>
<h1>我是父组件</h1>
<p>我的名字叫{{ name }}</p>
<l-e @xxxxx='fn1'></l-e>
</div>
`,
methods:{
fn1(){
console.log('父组件的fn1方法');
//组件还不能去修改,需要去根组件上修改
//还需要去传递到根元素上修改
// this.$emit('yyy')
bus.$emit('event1',{
index:'0',
name:'张三丰'
})
}
}
})
//跟实例
varvm =newVue({
el:'#app',
data:{
childs:[
'张三',
'李四',
'王五',
'马六'
]
},
methods:{
fn1(){
this.childs = ['老王','李四','王五','马六'];
console.log('我是根元素爷爷');
}
},
created () {
//实例方法,是来绑定事件的
//两个参数('自定事件’,回调函数fn)
bus.$on('event1',(event)=>{
// this.childs=['老王', '李四', '王五', '马六'];
console.log('进来了');
this.$set(this.childs,event.index,event.name);
})
}
})
</script>
3.组件之间的通信
<body>
<divid="app">
<l-p></l-p>
</div>
</body>
</html>
<scriptsrc="../js/vue.js"></script>
<script>
//定义子组件
Vue.component('l-e',{
props: ['name'],
template:`
<div>
<p>我是儿子我的名字是{{ name }}</p>
<button @click="fn1">名字太娘了,得叫我爸改名字</button>
</div>
`,
methods: {
fn1(){
// $emit('自定义事件的名字','传递过去的参数')
//参数是在标签上通过$event接收
this.$emit('xx','张三丰')
}
}
})
//定义父组件
Vue.component('l-p',{
data () {
return{
childName:'张珊'
}
},
template:`
<div>
<h1>我是父元素</h1>
<l-e :name="childName" @x ildName=$event"></l-e>
</div>
`,
methods: {
fn1(){
}
}
})
varvm =newVue({
el:'#app',
})
</script>
4.v-model 的简单应用
<body>
<divid="app">
<!--
1.调用组件的时候才需要v-model不能再组件里面使用
需要在组件里面使用valueh这个props
v-model="searchText"
相等于
value="searchText" @input="searchText=$event “
2.
3.
-->
<l-searchv-model="searchText"></l-search>
</div>
</body>
</html>
<scriptsrc="../js/vue.js"></script>
<script>
Vue.component('l-search',{
props: ['value'],
// $emit不仅仅可以出发自定义事件,原生也是可以触发的
template:`
<input type="text" :value="value" @input="$emit('input',$event.target.value)" />
`
})
varvm =newVue({
el:'#app',
data:{
searchText:'张三',
list:[]
}
})
</script>
5.solt内容分发
<body>
<divid="app">
<l-j>
听说加上了slot就可以在组件标签内写东西了????
</l-j>
</div>
</body>
</html>
<scriptsrc="../js/vue.js"></script>
<script>
Vue.component('l-j',{
template:`
<div>
<h1>我是一个l-j组件</h1>
<slot></slot>
</div>
`
})
varvm =newVue({
el:'#app'
})
</script>
6.动态组件
<body>
<divid="app">
<buttonv-for="(item,index) in tabs"
:key="index"
:style="{'color':curTab===item.id?'red':'blue '}"
@click="curTab=item.id">
{{item.name}}
</button>
<divclass="main">
<!-- Vue提供的一个内置组件动态组件-->
<component:is="'l-'+curTab"></component>
</div>
</div>
</body>
</html>
<scriptsrc="../js/vue.js"></script>
<script>
Vue.component('l-home', {
template:`
<div>
<h1>我是首页</h1>
</div>
`
})
Vue.component('l-list', {
template:`
<div>
<h1>我是列表页</h1>
</div>
`
})
Vue.component('l-about', {
template:`
<div>
<h1>我是关于页</h1>
</div>
`
})
varvm =newVue({
el:'#app',
data:{
tabs:[ {
id:'home',
name:'首页'
},
{
id:'list',
name:'列表页'
},
{
id:'about',
name:'关于页'
}],
curTab:'home'
}
})
</script>
网友评论