1.组件机制
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用is特性进行了扩展的原生 HTML 元素。组件注册的时候需要为该组件指定各种参数。
因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods
以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
js中,驼峰命名法
html中,短斜线命名法
组件的特点
1.组件可以进行任意次数的复用。
2. 组件的data必须是一个函数,确保每个实例可以维护一份被返回对象的独立的拷贝,也就是任何一个组件的改变不会影响到其他组件。
let component = {
data () {
return { count: 0 }
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
}
一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
2.组件注册
要想进行组件使用得先进行组件注册
1. 全局注册
可以使用Vue.component(tagName, options)
注册一个全局组件, 注册之后可以用在任何新创建的 Vue 根实例的模板中
<div id="app">
<my-com></my-com>
<my-com></my-com>
</div>
// 1.创建组件
let component= {
data() {
return {
msg: '子组件一'
}
},
template: `
<div>
{{msg}}
</div>
`
};
// 2.全局注册
Vue.component('my-com',component)
new Vue({
el: '#app',
data: {
},
})
2. 局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。局部注册的组件只能在当前组件中使用
全局组件–>全局变量
局部组件–>局部变量
<div id="app">
<my-com-a></my-com-a>
</div>
let myComA={
// 模板
template:`
<div>A组件</div>
`
};
Vue.component('my-com',component)
new Vue({
el: '#app',
components:{
'my-com-a':myComA
},
data: {
},
})
3. 组件交互/通信/传值
组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:父组件可能要给子组件下发数据,子组件则可能要将它内部发生的事情告知父组件。在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过prop
给子组件下发数据,子组件通过事件给父组件发送消息。
自定义事件
自定义事件是子组件向父组件传递状态的一种机制。事件名大小写严格区分。$emit
子组件
this.$emit('myEvent')
父组件
<my-component v-on:myEvent="doSomething"></my-component>
1.父组件给子组件传值
1.把想要传递的属性写在子组件标签中
<my-a title='我是父组件传递过来的值' :msg='msg' attr-b='我是驼峰式命名属性' @my-event='handler'></my-a>
2.在子组件内使用props进行传值的接收
1.把想要传递的属性写在子组件标签中
2.在子组件内使用props来进行属性的接收
3.在子组件模板内使用传递的属性
<div id="app">
<!-- 3.组件使用,第一个attr1是向子组件传递数据的名字,第二个attr1是声明的变量名-->
<my-com :attr1="attr1" :parent-data="attr2"></my-com>
</div>
<script>
// 1.组件定义
let component1={
//4.子接收父传递过来的数据 此时的attr1是第一个attr1,通过属性绑定形式传递过来的
props:['attr1','parentData'],
data(){
return{
msg:'子组件一'
}
},
template:`
<div>
<h3>{{msg}}</h3>
<h2>父组件传递过来的数据:{{attr1}}-{{parentData}}</h2>
</div>
`
}
let vm=new Vue({
el:"#app",
data:{
attr1:'我是父组件数据',
attr2:'父组件数据二'
},
methods:{},
//2.局部注册组件
components:{
'my-com':component1
}
})
</script>
2.子组件给父组件传值
1.在子组件模板中定义一个发射事件 触发`this.$emit();`1.自定义事件(和父组件事件处理程序绑定) 2.发送的数据
2.在子组件内绑定自定义事件,触发父组件的事件处理程序
3.在父组件事件处理程序内接收数据
<style>
.box {
width: 50px;
height: 50px;
border: 1px solid teal;
}
</style>
<body>
<div id="app">
<h2>父组件</h2>
<div class="box">
{{parentData}}
</div>
<!-- 接收子组件向上发送的事件 -->
<my-com v-on:child-event="parentHandler">
成功按钮
</my-com>
</div>
<script>
let component1 = {
data() {
return {
childData: 'Windows 11'
}
},
methods: {
toEmitHandler() {
// $emit方法可以向上发送事件,并且可以携带数据
this.$emit('child-event', this.childData)
}
},
template: `
<div>
<h3>子组件</h3>
<button @click="toEmitHandler">发送事件</button>
</div>
`
}
let vm = new Vue({
el: '#app',
data: {
parentData: 'window98'
},
methods: {
//data是子组件向上发送数据时携带的数据
parentHandler(data) {
console.log('你说的我知道了', data);
// 修改父组件数据,由父组件自己来决定
this.parentData = data
}
},
components: {
'my-com': component1
}
})
</script>
4.组件传值
父组件通过属性绑定的方式将参数传递给子组件,子组件通过props声明期望从父组件那里获取的参数。camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名:
希望每个prop都有指定的值类型。这时,你可以以对象形式列出prop,这些property的名称和值分别是prop各自的名称和类型
prop类型
父组件给子组件数据的时候,子组件可以定义数据类型
静态传参:不加冒号,传字符串
动态传参:加冒号,传number、boolean、object、数组类型的值,变量
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
}
prop验证
我们可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助。
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型 propB: [String, Number],
// 必填的字符串
propC: { type: String, required: true },
// 带有默认值的数字
propD: { type: Number, default: 100 }
})
动态传参
prop 可以通过v-bind
动态赋值。传递什么类型的变量就可以将该类型变量直接进行赋值,也可以赋常量。如果不使用v-bind就只能传递字符串。
单向数据流(数据更改的方向)
父组件可以改给子组件的数据
父改子可以
子组件不可以改父组件的数据
子改父不行修改父组件的msg 子组件的msg跟着修改但是反过来不行
vm.msg=‘hello vue’ 观察子组件的变化