组件化编码的基本流程:
1、拆分组件
2、静态组件(显示的界面数据是固定的,没有交互)
3、动态组件(初始化显示(动态展示出来)、交互)
1、组件定义与使用
01、vue文件的组成(3个部分)
1)、模板页面
页面模板
2)、JS模块对象
export default { data(){ return{ } }, methods:{}, computed:{}, components:{} }
3)、样式
样式定义
02、基本使用
1)、引入组件
2)、映射成标签
3)、使用组件标签
03、关于标签名与标签属性名书写问题
1)、写法一:一模一样
2)、写法二:大写变小写,并用-连接
2、组件间通信
01、组件间通信基本原则
1)、不要在子组件中直接修改父组件的状态数据
2)、数据在哪,更新数据的行为(函数)就应该定义在哪
02、vue组件间通信方式
1)、props
2)、vue的自定义事件
3)、消息订阅与发布(如:pubsub库)
4)、slot
5)、vuex(后面单独讲)
3、组件间通信 1:props
01、使用组件标签时
02、定义MyComponent时
1)、在组件内声明所有的props
2)、方式一:只指定名称
props:['name','age','setName']
3)、方式二:指定名称和类型
props:{
name:String,
age:Number,
setName:Function
}
4)、方式三:指定名称/类型/必要性/默认值
props:{
name: {type: String,required: true,default:xxx},
}
03、注意
1)、此方式用于父组件向子组件传递数据
2)、所有标签属性都会成为组件对象的属性,模板页面可以直接引用
3)、问题:
a. 如果需要向非子后代传递数据必须多层逐层传递
b. 兄弟组件间也不能直接props通信,必须借助父组件才可以
4、组件间通信 2:vue自定义事件
01、绑定事件监听
// 方式一:通过v-on绑定@delete_todo="deleteTodo"// 方式二:通过$on()this.$refs.xxx.$on('delete_todo',function(todo){ this.deleteTodo(todo)})
02、触发事件
// 触发事件(只能在父组件中接收)this.$emit(eventName,data)
03、注意:
1)、此方式只用于子组件向父组件发送消息(数据)
2)、问题:隔代组件或兄弟组件间通信此种方式不合适
5、组件间通信 3:消息订阅与发布(PubSubJS)
01、订阅消息
Pubsub.subscribe('msg',function(msg,data){})
02、发布消息
PubSub.publish('msg',data)
03、注意
1) 优点:此方式可实现任意关系组件间通信(数据)
04、事件的2个重要操作(总结)
1) 绑定事件监听(订阅消息)
目标:标签元素
事件名(类型):click/focus
回调函数:function(event){}
2) 触发事件(发布消息)
DOM事件:用户在浏览器上对应的界面上做对应的操作
自定义:编码手动触发
6、组件间通信 4:slot
01、理解
此方式用于父组件向子组件传递'标签数据'
02、子组件:Child.vue
<template> <div> <slot name="xxx">不确定的标签结构 1slot> <div>组件确定的标签结构div> <slot name="yyy">不确定的标签结构 2slot> div> template>
03、父组件:Parent.vue
<child> <div slot="xxx">xxx对应的标签结构div> <div slot="yyy">yyyy对应的标签结构div>child>
7、初始化显示(项目实战)
01、main.js文件
/** * 入口JS:创建Vue实例 */import Vue from 'vue'import App from './App.vue'new Vue({ el: '#app', components: {App}, template: ''})
02、index.html文件(引入css样式)
vue_demo
03、App.vue(引入静态组件)
请发表对Vue的评论
请发表对Vue的评论
//1、引入组件 import Add from './components/Add.vue' import List from './components/List.vue' export default { data () { return{ comments: [//数据在哪个组件,更新数据的行为(方法)就应该定义在哪个组件 { name: 'BOB', content: 'Vue 还不错' }, { name: 'Cat', content: 'Vue So Easy' }, { name: 'BZ', content: 'Vue So So' } ] } }, methods:{ //添加评论 addComment (comment) { this.comments.unshift(comment) }, //删除指定下标的评论 deleteComment (index) { this.comments.splice(index,1) } }, //2、映射组件标签 components: { Add, List } }
Add.vue
用户名
评论内容
提交
export default { props: { addComment: { // 指定属性名/属性值的类型/必要性 type: Function, required: true } }, data () { return { name: '', content: '' } }, methods:{ add(){ // 1、检查输入的合法性 const name = this.name.trim() const content = this.content.trim() if(!name || !content) { alert("姓名或内容不能空") return; } // 2、根据输入的数据,封装成一个comment对象 const comment = { name, content } // 3、添加到comments中 this.addComment(comment) // 4、清除输入 this.name = '' this.content = '' } } }
List.vue
评论回复:
评论回复:
暂无评论,点击左侧添加评论!!!
暂无评论,点击左侧添加评论!!!
:deleteComment="deleteComment" :index="index"/>
import Item from './Item.vue' export default { //声明接收属性:这个属性就会成为组件对象的属性 props: ['comments','deleteComment'], //只指定属性名 components: { Item } } .reply { margin-top: 0px; }
Item.vue
删除
{{comment.name}}说:
{{comment.content}}
export default { props: { //指定属性名和属性值的类型 comment: Object, deleteComment: Function, index: Number }, methods: { deleteItem () { const {comment,index,deleteComment} = this if(window.confirm('确定删除${comment.name}的评论吗?')){ deleteComment(index) } } } } li { transition: .5s; overflow: hidden; } .handle { width: 40px; border: 1px solid #ccc; background: #fff; position: absolute; right: 10px; top: 1px; text-align: center; } .handle a { display: block; text-decoration: none; } .list-group-item .centence { padding: 0px 50px; } .user { font-size: 22px; }style>