压缩elementui插件-这些Vue知识点可以解决你的卡点

转发链接:

前言

一阵按键声传来,隐隐约约地试探着话语。 产品不稳定,今晚没人退货。

在开发Vue的过程中,我们经常会遇到这样或那样的一些问题,然后不得不卡住很长一段时间。 问题解决后,我们发现原来的一些细节还没有把握好。 明天小编就整理一下项目中会用到的一些实用方法,希望能够帮助到正在为赚钱而苦苦挣扎的你。

数据无反应,可能使用有问题

前几天有同学给我发了一段代码,然后说vue有bug。 明明写的没有问题,为什么数据没有反应,一定是Vue的bug? 我以为他比尤玉溪强,我也承受不起,所以就没有理他。 而确实有时候我们在开发过程中会遇到数据无响应的情况,那么我们该怎么办呢? 例如下面这段代码:


  
    
      用户名: {{ userInfo.name }}       用户性别: {{ userInfo.sex }}                公众号: {{ userInfo.officialAccount }}            
       
export default {   data() {     return {       userInfo: {         name: '子君',         sex: '男'       }     }   },   methods: {     // 在这里添加用户的公众号     handleAddOfficialAccount() {       this.userInfo.officialAccount = '前端有的玩'     }   } }

前面的代码中,我们想要给用户信息添加公众号属性,添加this.userInfo.officialAccount='Backend Some Play'后,并没有生效。 为什么?

这是因为在Vue内部,数据响应是通过使用Object.definePrototype来监听对象各个key的getter和setter来实现的,但是通过这些方法,只能监听到已有的属性,新的属性很难监听到。 是的,不过我只是想偷听一下,小编你觉得呢? 下面小编提供了四种方法。 如果还有更多表格,请在下面评论区告诉我。

1、在data中定义预先添加的属性

比如之前的公众号,我可以提前定义在userInfo上,这样就不是新的属性了,如下图

data() {
    return {
      userInfo: {
        name: '子君',
        sex: '男',
        // 我先提前定义好
        officialAccount: ''
      }
    }
  }

2.直接替换userInfo

虽然不能给userInfo添加新的属性,而且由于userInfo已经被定义了,所以我直接改变userInfo的值是不够的,所以也可以写成如下

压缩elementui插件_压缩插件英文_压缩插件怎么安装

this.userInfo = {
  // 将原来的userInfo 通过扩展运算法复制到新的对象里面
  ...this.userInfo,
  // 添加新属性
  officialAccount: '前端有的玩'
}

3.使用Vue.set

虽然前面两种方法有点棘手,但是对于新属性,Vue官方提供了新方法Vue.set来解决新属性触发数据响应的困难。

Vue.set方法定义

/**
* target 要修改的对象
* prpertyName 要添加的属性名称
* value 要添加的属性值
*/
Vue.set( target, propertyName, value )

里面使用Vue.set的代码可以改为

import Vue from 'vue'
// 在这里添加用户的公众号
handleAddOfficialAccount() {
  Vue.set(this.userInfo,'officialAccount', '前端有的玩')
}

而且每次想要使用set方法,都得引入Vue,非常麻烦,所以为了简单起见,Vue将set方法挂载在Vue原型链上,即Vue.prototype.$set= Vue.set,所以在Vue组件内部可以直接使用this.$set代替Vue.set

this.$set(this.userInfo,'officialAccount', '前端有的玩')

小编发现很多朋友不知道什么时候该使用Vue.set。 当然,只有当你想要的形参的属性还没有定义时才需要使用Vue.set,其他时候通常不需要使用它们。

4.使用$forceUpdate

我认为 $forceUpdate 的存在让很多后端开发者无法关注单向数据绑定的原理,因为无论什么时候,我更改数据后,调用 $forceUpdate 都会让 Vue 组件重新渲染,错误不存在。 而事实上,这种方法并不推荐,因为它会造成很多不必要的性能消耗。

压缩插件怎么安装_压缩插件英文_压缩elementui插件

链表的具体形式

虽然不仅仅是对象,链表也有数据改变不响应的情况,比如下面的代码


  
  • {{ item }}
export default { data() { return { list: ['张三', '李四'] } }, methods: { // 修改用户名称 handleChangeName() { this.list[0] = '王五' } } }

里面的代码想要把张三的名字改成王五,但是这个改变并没有生效,因为Vue无法测量以下改变的字段:

当直接借助index设置一个item时,如:this.list[index]=newValue 改变字段的length属性,如:this.list.length=0

那么上面的例子中,很难通过this.list[0]='王五'来触发数据响应,那么该怎么办呢?上面提到的Vue.set和$forceUpdate都可以解决这个问题。 例如Vue.set可以这样写

Vue.set(this,list,0,'王五')

除了这些技术之外,Vue 还提供了字段的变异方法

在操作链表时,我们通常会用到数据提供的很多技术,比如push、pop、splice等,在Vue中调用链表提供的方法改变字段的值就可以触发数据响应,例如示例 将前面的代码改为下面的代码即可触发数据响应

this.list.splice(0,1,'王五')

事实上,如果Vue只依赖getter和setter,链表调用push、pop等时很难触发数据响应,所以Vue实际上是通过包装和变异的方式来实现这个方法的。 的。

Vue 对链表的包装器突变有以下几种方式:

因此,在操作字段时,调用该方法可以保证数据能够正常响应。 以下是Vue源码中包装链表方法的代码:

var original = arrayProto[method];
  def(arrayMethods, method, function mutator () {
    // 将 arguments 转换为数组
    var args = [], len = arguments.length;
    while ( len-- ) args[ len ] = arguments[ len ];
    var result = original.apply(this, args);
    // 这儿的用法同dependArray(value),就是为了取得dep
    var ob = this.__ob__;
    var inserted;
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args;
        break
      case 'splice':
        inserted = args.slice(2);
        break
    }
    // 如果有新的数据插入,则插入的数据也要进行一个响应式
    if (inserted) { ob.observeArray(inserted); }
   // 通知依赖进行更新
    ob.dep.notify();
    return result
  });

文本格式较低,过滤器更简单。 使用过滤器来简化逻辑

如果我想以yyyy-MM-DDHH:mm:ss的格式显示时间戳怎么办? 在将日期渲染到模板之前,是否需要先在代码中格式化日期?如下所示


  
{{ dateStr }}
  • {{ item.date }}
import { format } from '@/utils/date' export default { data() { return { date: Date.now(), list: [ { date: Date.now() } ] } }, computed: { dateStr() { return format(this.date, 'yyyy-MM-DD HH:mm:ss') }, getList() { return this.list.map(item => { return { ...item, date: format(item.date, 'yyyy-MM-DD HH:mm:ss') } }) } } }

和之前的写法一样,需要对每个日期数组调用format,然后通过估计属性进行转换?这时候可以考虑使用Vue提供的过滤器来简化


  
{{ dateStr | formatDate }}
  • {{ item.date | formatDate }}
import { format } from '@/utils/date' export default { filters: { formatDate(value) { return format(value, 'yyyy-MM-DD HH:mm:ss') } }, data() { return { date: Date.now(), list: [ { date: Date.now() } ] } } }

和之前的改动相比是不是简单多了?

注册全局过滤器

有些过滤器经常使用。 比如上面提到的日期过滤器,很多地方都会用到。 这时候如果你在每个要使用的组件上都定义它,就显得有点多余了。 这时候Hou可以考虑Vue.filter来注册全局过滤器

对于全局过滤器,通常建议在项目上方添加filters目录,然后添加到filters目录下

// filtersindex.js
import Vue from 'vue'
import { format } from '@/utils/date'
Vue.filter('formatDate', value => {
  return format(value, 'yyyy-MM-DD HH:mm:ss')
})

压缩插件怎么安装_压缩插件英文_压缩elementui插件

之后将上面的filters文件导入到main.js中,就可以直接在组件上使用了。 例如上面的代码可以改为


  
{{ dateStr | formatDate }}
  • {{ item.date | formatDate }}
export default { data() { return { date: Date.now(), list: [ { date: Date.now() } ] } } }

是不是更容易

开发了一个插件库,我们来安装一下

在使用一些UI框架的时候,往往需要使用Vue.use来安装。 例如,使用element-ui时,常常这样写:

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI,{size: 'small'});

使用Vue.use后,element-ui可以直接在组件上使用,太神奇了(yuck)。 接下来我们来实现一个简化版的element,看看如何安装。

了解Vue.use的用法

Vue.use 是一个全局方法。 它需要在调用 newVue() 启动应用程序之前完成。 Vue.use的参数如下

/**
* plugin: 要安装的插件 如 ElementUI
* options: 插件的配置信息 如 {size: 'small'}
*/
Vue.use(plugin, options)

模拟element-ui的安装逻辑

想一想,使用 Vue.use(ElementUI,{size:'small'}) 然后我们就可以使用 element-ui 提供的东西

可以直接在组件上使用element-ui组件,不需要导入,可以直接使用v-loading命令,通过this.$loading显示组件上的加载其他...

// 这个是一个按钮组件
import Button from '@/components/button'
// loading 指令
import loadingDirective from '@/components/loading/directive'
// loading 方法
import loadingMethod from '@/components/loading'
export default {
  /**
   * Vue.use 需要插件提供一个install方法
   * @param {*} Vue Vue
   * @param {*} options 插件配置信息
   */
  install(Vue, options) {
    console.log(options)
    // 将组件通过Vue.components 进行注册
    Vue.components(Button.name, Button)
    // 注册全局指令
    Vue.directive('loading', loadingDirective)
    // 将loadingMethod 挂载到 Vue原型链上面,方便调用
    Vue.prototype.$loading = loadingMethod
  }
}

通过前面的代码,已经实现了乞丐版的element-ui插件。 这时候就可以通过main.js上的Vue.use来安装插件了

插件的应用场景增加了全局的方法或者属性。 添加全局资源:指令/过滤器/转换等。通过全局混合添加一些组件选项。 通过将 Vue 实例添加到 Vue.prototype 来添加 Vue 实例的方法。 提供自己的 API 并提供其中提到的一个或多个函数的库。 如果 element-ui 提高了 Vue 渲染性能,请了解 Object.freeze

当创建 Vue 实例时,它将数据对象中的所有属性添加到 Vue 的反应系统中。 当这个属性的值发生变化时,视图会形成“响应”,即匹配更新为新值。 而这个过程实际上是消耗性能的压缩elementui插件,所以对于一些数据较多但只是显示的界面,不需要在响应式系统中添加属性,这样可以增强渲染性能。 怎么做压缩elementui插件,你需要了解Click on Object。 冻结。

在Vue官网上,有这样一段话:这里唯一的例外是使用Object.freeze(),这将阻止更改现有属性,也意味着响应系统无法再跟踪更改。 这段话的意思是,如果我们的数据使用Object.freeze,就可以将数据与响应式系统分离,那么我们该怎么办呢?

比如下表,由于只是渲染数据,此时我们可以使用Object.freeze来优化性能


  
    
    
    
  


export default {
  data() {
    const data = Array(1000)
      .fill(1)
      .map((item, index) => {
        return {
          date: '2020-07-11',
          name: `子君${index}`,
          address: '大西安'
        }
      })
    return {
      // 在这里我们用了Object.freeze
      tableData: Object.freeze(data)
    }
  }
}

有的朋友可能会有疑问,如果我表中的数据是通过滚动加载的,那么这样写我是不是就无法向tableData添加数据了?是的,确实没有办法添加数据,但是还是有办法的来解决它,比如下面的

export default {
  data() {
    return {
      tableData: []
    }
  },
  created() {
    setInterval(() => {
      const data = Array(1000)
        .fill(1)
        .map((item, index) => {
          // 虽然不能冻结整个数组,但是可以冻结每一项数据
          return Object.freeze({
            date: '2020-07-11',
            name: `子君${index}`,
            address: '大西安'
          })
        })
      this.tableData = this.tableData.concat(data)
    }, 2000)
  }
}

合理使用Object.freeze可以节省大量的渲染性能,尤其是对于IE浏览器,效果还是很显着的,赶紧尝试一下吧。

最后,如果你现在需要开发联通项目,可以了解一下小编编译的一个开箱即用的框架vue-vant-base,或许会对你有所帮助。

结语

不要耗尽你的灵感和想象力; 不要成为模型的奴隶。 - 文森特 - 梵高