kangkai124 / blog

开发笔记
https://kangkai124.github.io/blog/
MIT License
26 stars 4 forks source link

vue 知识点及问题汇总 #7

Open kangkai124 opened 5 years ago

kangkai124 commented 5 years ago

关于vue

kangkai124 commented 5 years ago

模拟已废弃 vue 1.x 的 $dispatch$broadcast 方法

实现以下功能:

kangkai124 commented 5 years ago

vue 组件使用 v-model

父组件

<template>
  <div>
    <Child v-model="list" />
  </div>
</template>
<script>
import Child from './Child'

export default {
  name: 'Parent',
  component: { Child },
  data () { return { list: [1,2,3] } }
}
</script>

子组件

<template>
  <div class="child" @click="newList">
    <img v-for="item in list" />
  </div>
</template>
<script>
export default {
  name: 'Child',
  model: {
    prop: 'list',
    event: 'new'
  },
  methods: {
    newList () {
      this.$emit('new', [4, 5, 6])
    }
  }
}
</script>
kangkai124 commented 5 years ago

computed 属性绑定过程

如官方给的例子

var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})
  1. data 属性初始化 getter, setter
  2. computed 计算属性初始化,接受的函数作为 vm.reversedMessage 的 getter
  3. 首次获取 reversedMessage 的值时,Dep 开始依赖收集
  4. 在执行 message getter 方法时,如果 Dep 处于依赖收集状态,则判定 message 为 reversedMessage 的依赖,建立依赖关系
  5. message 发生变化时,根据依赖关系,触发 reversedMessage 重新计算
kangkai124 commented 5 years ago

ivew 组件 Tabs 第一次切换标签内部 Table 卡顿问题

从折线图切换到到表格时,表格会卡顿一下。 WX20190411-102606@2x

<Tabs>
        <TabPane label="折线图" name="line-chart">
          <SimpleChart :data="data" />
        </TabPane>
        <TabPane label="表格" name="table">
          <SimpleGrid :data="data" :columns="columns" />
        </TabPane>
      </Tabs>

分析:进到 Modal 时,折线图和表格组件都已经渲染,但此时表格的 TabPane display:none,Table 获取不到宽高,所以渲染出来的数据堆在一条线上。当切换到表格时,display:block,Table 获取宽高撑开盒子,所以有了一瞬间的卡顿。

解决方法:使用 this.$nextTick 控制表格延迟渲染

<Tabs @on-click="onTabClick">
        <TabPane label="折线图" name="line-chart">
          <SimpleChart :data="data" />
        </TabPane>
        <TabPane label="表格" name="table">
          <SimpleGrid :data="data" :columns="columns" v-if="mount" />
        </TabPane>
      </Tabs>
export default {
    ...
    data () {
        return {
          mount: false
        }
    },
    methods: {
        onTabClick (name) {
            if (name === 'table') {
                this.$nextTick(() => {
                    this.clickTable = true
                })
            }
        }
    }
    ...
}
kangkai124 commented 5 years ago

Uncaught TypeError: timeout.close is not a function

使用了定时器,然后在 beforeDestory 里清除定时器:

  beforeDestroy () {
    if (this.timer) {
      clearInterval(this.timer)
      this.timer = null
    }
  },

但是浏览器提示有错误:

image

最后,,,发现是 vs code 自动给我加了段引用代码!!

import { clearInterval } from 'timers'

只要把上面那行代码删了就阔以了。

kangkai124 commented 5 years ago

程序化的事件侦听器

例如,你可能经常看到这种集成一个第三方库的模式:

// 一次性将这个日期选择器附加到一个输入框上
// 它会被挂载到 DOM 上。
mounted: function () {
  // Pikaday 是一个第三方日期选择器的库
  this.picker = new Pikaday({
    field: this.$refs.input,
    format: 'YYYY-MM-DD'
  })
},
// 在组件被销毁之前,
// 也销毁这个日期选择器。
beforeDestroy: function () {
  this.picker.destroy()
}

这里有两个潜在的问题:

你应该通过一个程序化的侦听器解决这两个问题:

mounted: function () {
  var picker = new Pikaday({
    field: this.$refs.input,
    format: 'YYYY-MM-DD'
  })

  this.$once('hook:beforeDestroy', function () {
    picker.destroy()
  })
}