Vuejs-组件化思想与应用

一,组件是什么?什么是组件化

  • Vue是一个类,实例化出Vue的实例 (因为一个页面里有一个实例就够了,所以我们也叫根实例)
  • 利用Vue.extend来创建组件,其实组件其实也是一个类
  • 可以理解为组件是Vue的子类

组件化这里不在简单介绍,引用vue官网的介绍:相关链接

image.png

对于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)

  • 上面代码中我们使用了插槽来实现由用户自己控制弹窗的主体内容

image.png

  当我们使用弹窗组件,并没有传入任何内容时,弹窗中会显示'弹窗内容'
  当我们写入对应节点内容和样式时,或替换为你写入的内容
复制代码
  • 具名插槽:在定义插槽时为插槽命名,使用的时候需要绑定为你定义的名称

    如上面代码中:

image.png
在调用该组件时,如果不指定使用该具名插槽,页面中不会显示该内容

如(使用情况):

image.png

4,过滤器(filters)

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号 | 指示

  • 局部过滤器:(组件中)
    如上面代码中:

    定义了一个过滤器方法capitalize方法,对传入的值进行操作

    image.png

    过滤器使用:

    image.png

    可能不少人会有问题,我直接使用’计算属性‘不行吗?
    答案可以的,计算属性依赖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>

官方推荐的多过滤器,按顺序执行的过滤器,前一个过滤器返回的值会传给一下个过滤器

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享