组件化你怎么看?
组件的使用必须在 Vue 实例挂载的 div 之内
拥有组件的三大步:
创建组件构造器
<!DOCTYPE html>
<html>
<script>
const cpnC = Vue.extend({
template: '
<div>
<h2>iiiiiii<h2>
<h3>sdfjsefi<h3>
</div>'
})
</script>
<html>
注册组件
Vue.component('my-cpn',cpnC)
//第一个参数是创建的标签名,
//第二个参数是创建组件构造器的方法名
//这样的注册方式注册的是全局组件</pre>
使用组件
组件实例对象
<body>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</body>
组件 简单点~
简化注册组件的方式:在 Vue 实例或其他组件构造器中添加 component 属性
<script>
const app = new Vue({
el:'#app',
components:{
cpn1:cpnC1,
cpn2:cpnC2
}
})
</script>
组件的创建、注册可以在任意其他组件中,或者在 Vue 实例中 官方文档的注册方式
Vue.component('my-component-name',{ })
//该组件名就是 Vue.component 的第一个参数
全局注册
直接通过 Vue 实例注册创建的组件意味着注册方式是全局的。也就是说他们再注册之后可以用在任何新创建的 Vue 根实例的(new Vue)的模板中
Vue.component('my-component-name',{
//..选项})
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
父组件与子组件的联系
如果是组件之间进行注册的话,那么最高级的组件其注册位置在 Vue 实例中,最高级不包括 Vue 实例,其实 Vue 实例是根组件
组件在哪里注册,就在哪里使用;在 Vue 实例中注册可以在全局中使用 、在其他组件中注册只能在其 他组件内使用
<script>
const cpnC = Vue.extend({
components:{
cpn1:cpnC1,
cpn2:cpnC2
}
})
</script>
组件的语法糖注册方式(创建组件的构造方法和注册一齐简写)
<script>
Vue.component('cpn1',{
template:{
`
<div>
<h2>iiiiiii<h2>
<h3>sdfjsefi<h3>
</div>
`
}
})
</script>
疑问在于,这样注册的组件算是全局组件还是局部组件呢?是算局部组件的,因为在组件内进行注册的,但是可以直接使用该组件
组件的 template 模板属性的抽离
1.把模版写在 中,通过添加 id 属性和组件相关联
在组件的template属性中添加模板的id即可
<template id="cpn">
<div>
<h2>
我是内容
</h2>
</div>
</template>
<script>
Vue.component('cpn',{
template:'#cpn'
})
</script>
2.使用 template 标签 ,同样的通过添加 id 属性 和组件相关联
template 标签必须放在挂载区内
<div id = "app">
<template id = "cpn">
<div>
<h2>
我是标题
</h2>
</div>
</template>
</div>
<script>
Vue.component('cpn',{
template:'#cpn'
})
const app = new Vue({
el:'#app'
})
</script>
组件中的数据存放
data()非对象类型
组件是一个单独功能模块 的封装:这个模块有属于自己的HTML模板,也应该有属于自己的数据 data(因为组件不能访问 Vue 实例中的data属性中的值,就算能访问,多个组件叠加的值不利于代码编写),组件拥有属于自己可以保存数据的地方
组件中的data属性为什么是一个函数
因为在重复使用同一个组件时,并不希望在修改其中一个组件的数据时其他组件的值也同时被修改,使用函数是为了让其中的每个组件的内存地址不同从而做到互不影响
<script>
const obj = {
counter:0
}
Vue.component('cpn',{
template:'#cpn',
data(){
return {
obj
}
}
})
</script>
这种情况就是多个组件的值会同时被修改
父子组件的通信
子组件是不能引用父组件或者 Vue 实例的数据的,但是在开发中,一些数据确实需要从上层传递到下层,比如在一个页面中从服务器中请求到很多数据,其中一部分数据并非由整个页面的大组件展示的,而是需要下面的小组件进行展示,这时我们不会让小组件再次发送网络请求,而是直接让大组件将数据传递给小组件
途径
-
通过props向子组件传递数据 -
通过事件向父组件发送消息
props 基本用法(父组件向子组件传递数据)
使用选项 props 来声明需要从父级接受到的数据
方法一:字符串数组,数组中的字符串就是传递时的名称
方法二:对象、对象可以设置传递时的类型,也可以设置默认值等
<body>
<div id = "app">
<cpn v-bind:cmovies = "movies" :cmessage = "message"></cpn> :相当于 v-bind
</div>
<template id = "cpn">
<div>
<h1>sdfsdf</h1>
<h3>
{{cmovies}}
</h3>
<h3>
{{cmessage}} 检测是否接收到父组件的值
</h3>
</div>
</template>
<script>
const app = new.Vue({
el:'#app',
data:{
message:'nihao',
movies:['还望','海贼','海尔'],
component:{
cpn
}
}
})
const cpn = {
template:"#cpn",
props:['cmovies','cmessage'],
data(){
return{}
},
methods:{
}
}
</script>
</body>
props 属性还可以提供类型限制或一定的默认值
<script>
const cpn = {
template:"#cpn",
props:{
cmovies:Array,
cmessage:String,
cmessage:{
type:String,
default:'aaaaa',
required:true
},
cmovies:{
type:Array,
default(){
return[]
}
}
}
}
</script>
<script>
Vue.component('my-component',{
pros:{
propA:Number
propB:[String,Number],
propC: {
type: String,
required: true
},
propD: {
type: Number,
default:100
},
propE: {
type: Object,
default: function(){
return: {message: 'hello'}
}
},
propF: {
validator: function (value) {
return ['success','warning','danger'].indexof(vaule) !== -1
}
}
}
})
</script>
props驼峰标识 的转换
使用组件时,接受父组件的值通常会有 利用驼峰标识定义的属性,这时我们需要利用 c- / 或者用 - 来连接词语
暂时标签内传值时不支持驼峰命名
<body>
<div id = "app">
<cpn :c-info = "info" :child-my-message = "message"></cpn>
</div>
</body>
<script>
const cpn = {
template:'#cpn',
props:{
cInfo:{ }
}
}
</script>
<body>
<div>
<h2>
{{cInfo}}
</h2>
<h2>
{{childMyMessage}}
</h2>
</div>
</body>
当模板中的标签过多时,需要使用一个总标签将其括起来,否则会报错
<template id = "cpn">
<div>
<h2>
{{cInfo}}
</h2>
</div>
</template>
子传父(自定义事件)
当子组件需要向父组件传递数据时就需要用到自定义事件
流程:在子组件中,通过$emit()来触发事件;在父组件中,通过v-on 来监听子组件事件(v-on不仅可以监听DOM事件,也可以监听自定义事件)
<body>
<div id="app">
<cpn @item-click="cpn-click"></cpn>
</div>
<template id="cpn1">
<div>
<button v-for="item in categories" @click='btnClick(item)'>{{item.name}}</button>
</div>
</template>
<script>
const cpn = {
template: '#cpn1',
data() {
return {.
categories: [
{ id: 'aaa', name: 'aaareinasdaif' },
{ id: 'bbb', name: 'fffreiasdanaif' },
{ id: 'ccc', name: 'gggreinasdaaif' },
{ id: 'ddd', name: 'hhhhhhhh' },
]
}
},
methods: {
btnClick(item) {
this.$emit('item-click',item)
}
}
}
const app = new Vue({
el: '#app',
components: {
cpn:cpn
},
methods: {
cpnClick(item) {
console.log('cpnClick',item);
}
}
})
</script>
```html
<script>
const cpn = {
template: '#cpn1',
data() {
return {.
categories: [
{ id: 'aaa', name: 'aaareinasdaif' },
{ id: 'bbb', name: 'fffreiasdanaif' },
{ id: 'ccc', name: 'gggreinasdaaif' },
{ id: 'ddd', name: 'hhhhhhhh' },
]
}
},
methods: {
btnClick(item) {
this.$emit('item-click',item)
}
}
}
const app = new Vue({
el: '#app',
components: {
cpn:cpn
},
methods: {
cpnClick(item) {
console.log('cpnClick',item);
}
}
})
</script></pre>
**错误思维**
![image.png](https://img-blog.csdnimg.cn/img_convert/ef8d865774ac3c9db91276c5ecd19a0a.png)
**正确思维**
![image.png](https://img-blog.csdnimg.cn/img_convert/9ee64e7af979242f9551e549a78d23d1.png)
|