组件
<!--
一个包含html,css,js的独立集合体,这样的集合体可以完成页面结构的代码复用
-->
组件分类:
<!--
组件分为: 根组件,全局组件,局部组件
- 根组件:所有被new Vue()产生的组件,在项目开发阶段,一个项目只会出现一个根组件
- 全局组件:不用注册,就可以成为任何一个组件的子组件
- 局部组件:必须注册,才可以成为注册该局部组件的子组件
-->
<!--
每一个组件都有自身的html结构,css样式,js逻辑
- 每一个组件其实都有自己的template,就是用来标识自己html结构的
- template模板中有且只能有一个标签
- 根组件内一般不需要提供template,就由挂载点的真实DOM提供html结构
-->
补充:
- template模板为组件提供所需的html结构
- template模板中的html结构是虚拟DOM,仅存在内存中
- 根组件中的template模板中的标签会替换根组件所挂载的真是DOM标签(挂载点不能是html和body标签的原因)
- 根组件:
<body>
<div id="app">
<!-- 不会被渲染,因为div标签被tempalte模板中的标签替换 -->
<p>{{ msg }}</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: 'message',
c1: 'red'
},
template: `
<div :style="{color: c1}" @click="fn">{{ msg }} {{ msg }}</div>
`,
methods: {
fn() {
alert(this.msg)
}
}
});
</script>
- 局部组件
<!-- 步骤:
1) 创建局部组件(同创建字典方式)
2) 创建该局部组件的html结构
3) 在父组件中的components内注册该局部组件
4) 在父组件的template模板(所挂载的标签)中以自定义标签的形式渲染该局部组件
-->
<body>
<div id="app">
<!-- 4.在父组件的template模板(所挂载的标签)中以自定义标签的形式渲染该局部组件 -->
<local-tag></local-tag>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 1.创建局部组件(同创建字典方式)
let localTag = {
// 2.创建该局部组件的html结构
template:`
<div class="box">
<img src="img/666.jpg" alt="">
<h3>❤</h3>
<p>lilei❤hamm</p>
</div>
`
};
new Vue({
el: '#app',
// 3.在父组件中注册局部组件
components:{
'local-tag': localTag,
}
})
- 全局组件
<!--
1) 创建全局组件(全局组件类似Vue实例)
2) 在父组件的template模板(所挂载的标签)中以自定义标签的形式渲染该局部组件
注意:
- 你不需要在父组件中注册
-->
<script>
Vue.component('组件名',{
// 组件成员
});
</script>
<body>
<div id="app">
<!-- 2)在父组件的template模板(所挂载的标签)中以自定义标签的形式渲染该局部组件 -->
<global-tag></global-tag>
<global-tag></global-tag>
<global-tag></global-tag>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 1) 创建全局组件(全局组件类似Vue实例)
Vue.component('global-tag',{
template:`
<div class="box" @click="action">
<img src="img/666.jpg" alt="">
<h3>❤</h3>
<p>❤{{ num }}</p>
</div>
`,
// 数据局部化分析导入(利用函数的名称空间知识点:函数每实例化一次都会产生新的名称空间)
data:function () {
return { num:0 }
},
methods:{
action(){
this.num++
}
}
});
// 全局组件不需要再父组件中注册
new Vue({
el: '#app'
})
</script>
- 组件交互 | 父传子
<!--
数据交互 - 父传子 - 通过绑定属性的方式
1) 父组件提供数据
2) 在父组件模板中,为子组件标签设置自定义属性,属性的值由父组件提供
3) 在子组件实例中,通过props实例成员获得自定义属性
-->
<body>
<div id="app">
<info v-for="item in infos" :myinfo="item" :key="info.image"></info>
</div>
</body>
<script src="js/vue.js"></script>
<script>
let infos = [
{
image: 'img/001.png',
title: '小猫'
},
];
let info = {
template:`
<div class="info">
<img :src="myinfo.image" alt="">
<p><b>{{ myinfo.title }}</b></p>
</div>
`,
// 获取自定义属性 myinfo,此时的myinfo是个字典
props:['myinfo']
};
new Vue({
el: '#app',
// 父组件提供数据
data:{
infos,
},
components:{
info,
}
})
</script>
- 组件交互 | 子传父
<!--
组件交互-子传父
1) 数据由子组件提供
2) 子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来
3) 父组件为子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数
-->
<body>
<div id="app">
<p>
<input type="text" v-model="userMsg">
<button @click="sendMsg">留言</button>
</p>
<ul>
<msg-li @remove_msg="removeAction" v-for="(msg, i) in msgs" :msg="msg" :index="i" :key="msg"></msg-li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script>
let msgLi = {
template: `
<li>
<span class="close" @click="deleteMsg(index)">x </span>
<span>第{{ index + 1 }}条:</span>
<span>{{ msg }}</span>
</li>
`,
props: ['msg', 'index'],
methods: {
// 系统的click事件
deleteMsg(i) {
// $emit('自定义事件名', 参数们)
this.$emit('remove_msg', i);
this.$emit('myclick', 1, 2, 3, 4, 5)
}
}
};
// 组件交互-子传父
// 1) 数据由子组件提供
// 2) 子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来
// 3) 父组件位子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数
new Vue({
el: '#app',
data: {
msgs: [],
userMsg: ''
},
methods: {
sendMsg() {
if (this.userMsg) {
this.msgs.push(this.userMsg);
this.userMsg = "";
}
},
removeAction(i) {
this.msgs.splice(i, 1)
}
},
components: {
msgLi
}
})
</script>