Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue 注意相关 #13

Open
buddywang opened this issue Sep 30, 2020 · 1 comment
Open

Vue 注意相关 #13

buddywang opened this issue Sep 30, 2020 · 1 comment
Labels

Comments

@buddywang
Copy link
Owner

buddywang commented Sep 30, 2020

更新数组和对象问题

对象

Vue 无法检测 property 的添加或移除

  • 可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property,当添加多个 property 时,在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象
// 添加单个 property
this.$set(this.someObject,'b',2)

// 添加多个 property
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

数组

Vue 不能检测以下数组的变动:

    1. 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
    • 解决方法:
    vm.$set(vm.items, indexOfItem, newValue)
    
    1. 当你修改数组的长度时,例如:vm.items.length = newLength
    • 解决方法:
    // 索引大于或等于 newLength 的被删除
    vm.items.splice(newLength)
    

自定义指令

插件

插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:

  • 添加全局方法或者 property。如:vue-custom-element
  • 添加全局资源:指令/过滤器/过渡等。如 vue-touch
  • 通过全局混入来添加一些组件选项。如 vue-router
  • 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
  • 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router
MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或 property
  Vue.myGlobalMethod = function () {
    // 逻辑...
  }

  // 2. 添加全局资源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 逻辑...
    }
    ...
  })

  // 3. 注入组件选项
  Vue.mixin({
    created: function () {
      // 逻辑...
    }
    ...
  })

  // 4. 添加实例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 逻辑...
  }
}

nextTick 理解

nextTick 把回调函数放到本次事件循环的 microtask 队列中去

@buddywang buddywang changed the title Vue 问题总结 Vue 难点相关 Sep 30, 2020
@buddywang buddywang added the vue label Oct 13, 2020
@buddywang
Copy link
Owner Author

buddywang commented Oct 15, 2020

自定义事件

事件名

v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent——导致 myEvent 不可能被监听到。
因此,我们推荐你始终使用 kebab-case 的事件名。

将原生事件绑定到组件

Vue 提供了一个 $listeners property,它是一个对象,里面包含了作用在这个组件上的所有监听器。例如:

{
  focus: function (event) { /* ... */ }
  input: function (value) { /* ... */ },
}

有了这个 $listeners property,你就可以配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素,例如:

Vue.component('base-input', {
  inheritAttrs: false,
  props: ['label', 'value'],
  computed: {
    inputListeners: function () {
      var vm = this
      // `Object.assign` 将所有的对象合并为一个新对象
      return Object.assign({},
        // 我们从父级添加所有的监听器
        this.$listeners,
        // 然后我们添加自定义监听器,
        // 或覆写一些监听器的行为
        {
          // 这里确保组件配合 `v-model` 的工作
          input: function (event) {
            vm.$emit('input', event.target.value)
          }
        }
      )
    }
  },
  template: `
    <label>
      {{ label }}
      <input
        v-bind="$attrs"
        v-bind:value="value"
        v-on="inputListeners"
      >
    </label>
  `
})

现在 组件是一个完全透明的包裹器了,也就是说它可以完全像一个普通的 元素一样使用了:所有跟它相同的 attribute 和监听器都可以工作.

-----------------------------------

注意

以下适用于 Vue2.xx,在 Vue3.xx 里,用 v-model 替代

Vue 组件选项之 model

允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。

上面的话什么意思呢,比如在一个自定义组件上使用 v-model

<my-input v-model="num"></my-input>

上面的写法等价于:

<my-input :value="num" @input="(val)=> num = val"></my-input>

可以看出,在自定义组件上使用 v-model 就默认了组件的 props 有一个 value 属性(需要在组件里的 props 手动加上)和一个 input 事件(要在组件里手动通过 $emit 来触发该事件);这就默认占用了组件 props 里的 value 这个命名空间,但如果想要改变这个默认的命名空间,就可以在定义组件时使用 model

....
<script>
export default {
    model: {
        prop: 'parentValue',
        event: 'parentInput'
    },
    props: {
        value: Number,
        parentValue: Number
    },
....
}
</script>

这样,就可以把默认占用的 prop value 改为了 parentValue,把默认的事件 input 改为了 parentInput ,这样你就可以使用 value 这个 prop 来干其他事情了。现在在一个自定义组件上使用 v-model

<my-input v-model="num" :value="otherProp"></my-input>

等价于:

<my-input :parentValue="num" @parentInput="(val)=> num = val" :value="otherProp"></my-input>

启示

默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event

根据以上描述,也可以把 v-model 用于不限于表单元素上,以实现跟 .sync 同样的功能

----------------------------------------------

.sync 修饰符

<text-document v-bind:title.sync="doc.title"></text-document>

等价于

<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event"
></text-document>

在组件里要用 this.$emit('update:title', newTitle) 来触发父组件数据的更新

注意

  • 带有 .sync 修饰符的 v-bind 不能和表达式一起使用;
  • 假设 doc 是一个包含 title 和 content 属性的对象,使用 v-bind.sync="doc" 会把 doc 里的每一个 property (如 title) 都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器。

@buddywang buddywang changed the title Vue 难点相关 Vue 注意相关 Oct 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant