一,组件是什么?什么是组件化
- Vue是一个类,实例化出Vue的实例 (因为一个页面里有一个实例就够了,所以我们也叫根实例)
- 利用Vue.extend来创建组件,其实组件其实也是一个类
- 可以理解为组件是Vue的子类
组件化这里不在简单介绍,引用vue官网的介绍:相关链接
对于vue中的组件化,个人观点是:万物皆是对象,对象里包含许多的属性,其实组件也大致相同。前端开发应该具备组件化思想,把一些重复性高,高耦合的节点封装为单一组件,在使用的时候按需调用就很nice。
二,组件的运用
1,组件基本代码
这里以项目中常见的弹窗代码为例子:
//zIndex 为防止多个弹窗时 最后一个弹窗层级要高
<template>
<div class="dialog-model" v-if="visible" :style="{'z-index': zIndex}">
<div class="dialog-mark" @click.self="maskClose?closeDialogModel():''" :style="{'z-index': zIndex + 1}"></div>
<transition name="dialog-transition">
<div class="dialog-main">
<!-- 标题 -->
<slot name="dialog-header"></slot>
<!-- 弹窗内容 -->
<section class="dialog-body">
<slot>弹窗内容{{hasValue|capitalize}}</slot>
</section>
</div>
</transition>
</div>
</template>
<script>
export default {
name: 'DialogModel',
//组件接收值,不建议使用[]接收,建议使用{},定义接收的type:类型,default:默认值,required:是否必传。
//好处:约束父组件传入字段类型,传入错误类型控制台输出错误提示
props: {
drawer: {
type: Boolean,
default: false,
required: true,
},
//是否允许点击遮罩关闭
maskClose:{
type: Boolean,
default: true
}
},
data() {
return {
bodyOverflow: '',
hasValue:'',
}
},
//过滤器
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
computed: {
//计算属性监听
visible: {
get() {
return this.drawer
},
set(val) {
this.$emit('update:drawer', val)
}
}
},
watch: {
//监听visible变化 执行对应的操作
visible(val) {
if (val) {
/*你的操作*/
}
}
},
mounted() {
this.prohibitScroll()
},
methods: {
/** 每次获取之后 zindex 自动增加 */
getzIndex() {
let zIndexInit = 20190315;
return zIndexInit++
},
/** 点击遮罩关闭弹窗 */
closeDialogModel(event) {
this.drawer = false;
//派发事件给父组件,告诉父组件弹窗关闭
this.$emit('close', this.drawer)
this.renewBodyOverflow()
},
/** 禁止页面滚动 */
prohibitScroll() {
this.bodyOverflow = document.body.style.overflow
document.body.style.overflow = 'hidden'
},
/** 恢复页面的滚动 */
renewBodyOverflow() {
document.body.style.overflow = this.bodyOverflow;
},
}
}
</script>
<style lang="less" scoped>
/*css代码:不建议直接在vue文件中写样式(如果样式表比较简单,可以忽略)*/
/*建议:通过导入方式 如下*/
@import "./styles/index.less";
</style>
复制代码
2,组件的使用
父组件代码:
<template>
<div>
<button @click="visible=true"></buttom>
<dialog-model :drawer.sync="visible" @close='closeModel'>
<div slot="dialog-header">你的弹窗头部节点</div>
<!-- 或者使用该方法: <template v-slot:dialog-header>
<div>你的弹窗头部节点</div>
</template>-->
<div>你的弹窗主体内容</div>
</dialog-model>
</div>
</template>
<script>
import DialogModel from './component/DialogModel'
export default {
name: '',
data() {
return {
visible:false,
}
},
computed: {
},
watch: {
},
mounted() {},
methods: {
closeModel(val){
console.log(val); // false
}
}
}
</script>
<style lang="less" scoped>
</style>
复制代码
三,认识代码中知识点
凡事预则立,不预则废,做事前要熟悉其怎么运行
代码中简单的已加注释,这里不再赘述
1,计算属性:computed
计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 你data上要计算的值 还没有发生改变,多次访问 计算属性上你写的值(如:visible) 计算属性会立即返回之前的计算结果,而不必再次执行函数
2,监听器(侦听器):watch
watch来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,可以使用watch。
对于简单的属性(如字符串,number)可以直接:
a(val, oldVal){//普通的watch监听
console.log("a: "+val, oldVal);
},
复制代码
如果处理复杂结构的监听(如,监听对象obj下某个属性的变化),就需要使用深度监听
如:
b:{//深度监听,可监听到对象、数组的变化
handler(val, oldVal){
console.log("b.c: "+val.c, oldVal.c);
},
deep:true, //true 深度监听
immediate:true
}
复制代码
- 使用watch时有一个特点,就是当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。
immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。
- 设置deep: true 则可以监听到b.c的变化,此时会给b的所有属性都加上这个监听器,当对象属性较多时,每个属性值的变化都会执行handler。如果只需要监听对象中的一个属性值,则可以做以下优化,
使用字符串的形式监听对象属性:
'b.c': {
handler(newName, oldName) {
// ...
},
deep: true,
immediate: true
}
复制代码
使用监听器处理data中某个属性时,建议对其克隆出一个对应的属性,在克隆出的属性上操作,避免由于代码错误而使程序内存泄漏。
3,插槽(solt)
- 上面代码中我们使用了插槽来实现由用户自己控制弹窗的主体内容
当我们使用弹窗组件,并没有传入任何内容时,弹窗中会显示'弹窗内容'
当我们写入对应节点内容和样式时,或替换为你写入的内容
复制代码
-
具名插槽:在定义插槽时为插槽命名,使用的时候需要绑定为你定义的名称
如上面代码中:
在调用该组件时,如果不指定使用该具名插槽,页面中不会显示该内容
如(使用情况):
4,过滤器(filters)
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号 | 指示
-
局部过滤器:(组件中)
如上面代码中:定义了一个过滤器方法capitalize方法,对传入的值进行操作
过滤器使用:
可能不少人会有问题,我直接使用’计算属性‘不行吗?
答案可以的,计算属性依赖data上的属性变化,变化返回对应新值,要重新计算,个人认为这就有点消耗内存
过滤器出现是处理一些文本的格式化,或者内容替换,这些情况使用过滤器,会比较好吧。 -
全局过滤器
在项目工具文件夹中定义一个过滤器文件filters.js
import Vue from "vue"; Vue.filter("capitalize", (value) => { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) }); `` 在main.js中引入该文件,就可以在整个项目中使用定义的过滤器方法。 复制代码
过滤器可以使用多个:
<div v-bind:id="需要过滤的值 |过滤器方法1|过滤器方法2|过滤器方法3"></div>
官方推荐的多过滤器,按顺序执行的过滤器,前一个过滤器返回的值会传给一下个过滤器