组件化入门
和之前js普通开发的区别
组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树
如何使用
- 非单文件组件
-
使用entend进行创建
-
使用component创建
- 其实是entend的语法糖,一般使用这个
-
将template摘出去
- 这样写便捷,也有提示
<!-- 在被控制的 #app 外面 ,使用template元素 , 定义组件的HTML模板结构 -->
<template id="tmp1">
<div>
<h1>这是通过 template 元素,在外部定义的一个组件结构</h1>
</div>
</template>
- 组件中的data, methods
组件中的data必须是一个对象
- 全局注册
全局可用
Vue.component('todo-item', {
template: `<div>hah</div>`
})
Vue.component('hello', HelloWorld)
- 局部注册
只是在注册的那一块可以使用
var ComponentA = {
template: '<h2>哈哈</h2>'
}
Vue.component('myCom3', {
template: '#tmp1',
components: {
'component-a': ComponentA
}
})
-
单文件组件
- 在一个.vue文件中集成了Html,Css,Js。实现应用中局部功能代码和资源的集合
-
注意点:
- 组件名:
- 使用Kebab-case方式
- 使用 PascalCase
// Kebab-case
Vue.component('my-component-name', { /* ... */ })
// PascalCase
Vue.component('MyComponentName', { /* ... */ })
父子组件中的传值
想想两个设备间的交流, use插口
-
父组件向子组件传值
通过props,父组件传入,子组件通过props接收。
props的使用
基本使用
export default {
props: ["obj"],
};
类型检测
props: {
lists: {
type: Array,
default: function () {
return ["haha"];
},
},
},
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
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(value) !== -1
}
}
}
})
-
子组件向父组件传值
直接改变父组件的值
使用emits
- 推荐使用kebab-case的事件名
- 通过绑定自定义事件
// 在父组件中
<Main :lists="lists" @add="addOne"></Main>
// 在子组件中
<button @click="addItem">add</button>
emits: {
add: null,
},
methods: {
addItem() {
this.$emit("add", "我是子组件事件");
},
},
-
插槽的使用
将 <slot> 元素作为承载分发内容的出口。
- 插槽中的slot将会和组件标签中插入的元素进行替换, 也可以给slot中添加默认元素
- 可以插入文字,组件,标签
- 可以给插槽起名字,不起名字默认为default,在一个组件中添加多个插槽
// 父组件中
<template>
<div>
<nav-bar>
<template #left> // 用template包裹, #是 v-slot:的缩写
<button>左边的按钮</button>
</template>
<template #center>
<h2>我是标题</h2>
</template>
<template #right>
<i>右边的i元素</i>
</template>
</nav-bar>
</div>
</template>
// nav-bar 中
<template>
<div class="nav-bar">
<!-- <slot name="default"></slot> -->
<div class="left">
<slot name="left"></slot>
</div>
<div class="center">
<slot name="center"></slot>
</div>
<div class="right">
<slot name="right"></slot>
</div>
</div>
</template>
- 作用域插槽
- 前置问题:编译作用域, 默认只能取到自己的。
- 将子组件中的数据绑定到slot标签上,提供接口,在父组件中使用的时候,使用v-slot进行接收
// 子组件
<slot :title="title"></slot>
data() {
return {
title: "我是title",
};
},
// 父组件
<child-cpn v-slot:default="user"> // 前面声明插槽名
<p>{{ user.title }}</p>
</child-cpn>
- 如果只有默认插槽可以省略插槽名 v-slot="user"
-
访问元素和组件
尽量避免在vue中手动操作DOM
- 通过 this.$root 获取根组件
- 通过 this.$parent 获取父组件
- 通过在标签或者组件上添加ref属性来实现绑定,通过this.$refs调用
<!-- 绑定到一个元素上 -->
<h2 ref="title">哈哈哈</h2>
<!-- 绑定到一个组件实例上 -->
<nav-bar ref="navBar"></nav-bar>