zoukankan      html  css  js  c++  java
  • 在老项目中单独引入vue.js,使用自定义指令

    传统项目,做一个表格渲染,然而数据过多,传统方式费时费力,便引入vue和elelment  ui,由于表格需要渲染的数据过多一个表格上千条,导致切换tab更新表格时缓慢,体验太差,于是做了自定义指令,v-loadmore下拉加载更多,先上代码、

    <div id="detailTable2" style="display: none; margin: 0; padding: 0; height: 0;color:#fff;">
    <template>
    <el-table v-bind:data="deatilTable" v-loadmore="loadMore" border style=" 100%" height="400">
    <el-table-column prop="DataDateStr" label="时间" align="center" width="314"></el-table-column>
    <el-table-column prop="DataValue1" label="00分" align="center" width="250"></el-table-column>
    <el-table-column prop="DataValue2" label="15分" align="center" width="250"></el-table-column>
    <el-table-column prop="DataValue3" label="30分" align="center" width="250"></el-table-column>
    <el-table-column prop="DataValue4" label="45分" align="center" width="250"></el-table-column>
    </el-table>
    </template>
    </div>

    function renderDetailTable(HistoryDetailTableInfos, detailTem) {
    //加载表数据
    var Main = {
    methods: {
    dateFormat: function (row, column) { //时间格式化
    var date = row[column.property];
    if (date == undefined) {
    return "";
    }
    return formatMonthDate(date);
    },
    dateFormatYMD: function (row, column) { //时间格式化
    var date = row[column.property];
    if (date == undefined) {
    return "";
    }
    return formatMonthDateYMD(date);
    },
    loadMore:function() {
    if (this.page >= HistoryDetailTableInfos.length) {
    return;
    }
    this.page += 20;
    this.deatilTable=HistoryDetailTableInfos.slice(0, this.page)


    }
    },
    data: function () {
    return {
    deatilTable: HistoryDetailTableInfos.slice(0,20),
    page:20
    }
    }
    };

    //加载表数据(divtemplate模板需重新加载)
    $("#detailTableLoad").html($(detailTem).html());
    var Ctor = Vue.extend(Main);
    Vue.directive('loadmore', {
    bind(el, binding) {
    const selectWrap = el.querySelector('.el-table__body-wrapper')
    selectWrap.addEventListener('scroll', function () {
    let sign = 0
    const scrollDistance = this.scrollHeight - this.scrollTop - this.clientHeight
    if (scrollDistance <= sign) {
    binding.value()
    }
    })
    }
    })
    new Ctor().$mount('#detailTableScroll');
    }

    使用Vue.directive自定义指令需要了解

    钩子函数

    一个指令定义对象可以提供如下几个钩子函数 (均为可选):

    • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
    • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
    • unbind:只调用一次,指令与元素解绑时调用。

    接下来我们来看一下钩子函数的参数 (即 elbindingvnode 和 oldVnode)。

    钩子函数参数

    指令钩子函数会被传入以下参数:

    • el:指令所绑定的元素,可以用来直接操作 DOM 。
    • binding:一个对象,包含以下属性:

      • name:指令名,不包括 v- 前缀。
      • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
      • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
      • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
      • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
      • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
    • vnodeVue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
    • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

    特别说明

    如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。

    <div v-demo="{ color: 'white', text: 'hello!' }"></div>
    Vue.directive('demo', function (el, binding) {
      console.log(binding.value.color) // => "white"
      console.log(binding.value.text)  // => "hello!"
    })


    所以上面的v-loadmore="loadMore"传入的是一个方法
    loadMore

    而binding.value=this.loadMore,则
    binding.value()=this.loadMore(),所以在给el下class为.el-table__body-wrapper的DOM绑定监听滚动事件,滚动到底部,执行this.loadMore(),从而达到下拉加载更多的效果,也使切换表格不用一次加载过多数据导致显示缓慢,优化用户体验。


    再看看

    Vue.extend

    Vue.extend 属于 Vue 的全局 API,在实际业务开发中我们很少使用,因为相比常用的 Vue.component 写法使用 extend 步骤要更加繁琐一些。但是在一些独立组件开发场景中,Vue.extend + $mount 这对组合是我们需要去关注的。

    官方文档

    学习开始之前我们先来看一下官方文档是怎么描述的。

    Vue.extend( options )

    • 参数

      • {Object} options
    • 用法

      使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

      data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数

      <div id="mount-point"></div>
      // 创建构造器
      var Profile = Vue.extend({
        template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
        data: function () {
          return {
            firstName: 'Walter',
            lastName: 'White',
            alias: 'Heisenberg'
          }
        }
      })
      // 创建 Profile 实例,并挂载到一个元素上。
      new Profile().$mount('#mount-point')

      结果如下:

      <p>Walter White aka Heisenberg</p>
    • 参考组件

    可以看到,extend 创建的是 Vue 构造器,而不是我们平时常写的组件实例,所以不可以通过 new Vue({ components: testExtend }) 来直接使用,需要通过 new Profile().$mount('#mount-point') 来挂载到指定的元素上。

    为什么使用 extend

    在 vue 项目中,我们有了初始化的根实例后,所有页面基本上都是通过 router 来管理,组件也是通过 import 来进行局部注册,所以组件的创建我们不需要去关注,相比 extend 要更省心一点点。但是这样做会有几个缺点:

    1. 组件模板都是事先定义好的,如果我要从接口动态渲染组件怎么办?
    2. 所有内容都是在 #app 下渲染,注册组件都是在当前位置渲染。如果我要实现一个类似于 window.alert() 提示组件要求像调用 JS 函数一样调用它,该怎么办?

    这时候,Vue.extend + vm.$mount 组合就派上用场了。

    简单示例

    我们照着官方文档来创建一个示例:

    import Vue from 'vue'
    
    const testComponent = Vue.extend({
      template: '<div>{{ text }}</div>',
      data: function () {
        return {
          text: 'extend test'
        }
      }
    })

    然后我们将它手动渲染:

    const extendComponent = new testComponent().$mount()

    这时候,我们就将组件渲染挂载到 body 节点上了。

    我们可以通过 $el 属性来访问 extendComponent 组件实例:

    document.body.appendChild(extendComponent.$el)


    参考链接https://www.cnblogs.com/hentai-miao/p/10271652.html
  • 相关阅读:
    2
    异常处理
    接口
    抽象与多态
    关联关系
    9-13
    数据类型转换
    Day3
    对象和类
    MyEclipse导入现成项目出现小红叉错误
  • 原文地址:https://www.cnblogs.com/yszblog/p/11694256.html
Copyright © 2011-2022 走看看