绑定的 value 值和元素的 value 值

今天在刷思否的时候遇到这样的一个问题:

<template>
  <input type="text" :value="inputValue" @input="handleInput" />
</template>

<script setup>
import { ref } from 'vue'
const inputValue = ref('')
const handleInput = (e) => {
  const val = e.target.value
  const reg = /^\d*$/
  if (reg.test(val)) {
    inputValue.value = val
  } else {
    inputValue.value = ''
  }
}
</script>

题主希望通过正则校验去限制输入框只能输入数字类型的值,但是只有在先输入数字再输入非数字的情况下才会被正确置空。如果一开始就是输入非数字的内容,后续即使继续输入非数字内容,输入框中的内容并不会清空。

我们可以在 Vue SFC Playground 中体验这个现象。

阅读全文

为什么v-model绑定的对象属性不是总是响应式?

v-model 仅仅只是 v-bind:value="value"@input="value = $event.target.value" 的语法糖吗?

一直以来我都喜欢在Vue中声明对象变量的时候给变量赋值一个空对象,而不是把所有的属性值一起声明好。
比如说:

// vue2.x form demo
export default {
  data() {
    return {
      // 我喜欢这样声明
      formData: {},
      // 而不是这样在声明时把所有的属性一起书写好 
      formData: {
        username: '',
        password: ''
      }
    }
  }
}

也可以从我之前关于 props 属性的笔记中察觉到 👉 Vue中接收没有声明的Prop属性[null/undefined]的接收问题

因为我在写业务的时候如果 props 的属性值不存在,传入的会是一个 undefined 而不是 null 或者 '' 这样的预设。因为我期望使用组件 props 中声明的默认值,而不是在外部预设的空值
所以一直以来我都在和小伙伴交流的时候也是推荐直接给变量一个空对象即可,除了一些数组属性需要单独声明。

但前段时间一位小伙伴向我提问:他在组件生命周期函数中给表单属性赋值了一个预设值,后续再使用 v-model 对表单属性修改时发现丢失了响应……

阅读全文

聊一个VueJS的DOM模板解析注意事项

今天在社区答题的时候,遇到一个题目 《CDN引入的 Vue3 和Element Plus 表格异常,怎么解决呢?》。在去复现的时候和提问者犯了一样的错误。没有显式地写出关闭标签,想当然的直接复制了官方的代码示例就粘贴上去运行了。

问题图片预览

然后还以为是 CDN 上最新版本的包有问题,从 2.2.32 一路试到了 2.0.0 都还是一样情况,然后很果断地得出了一个结论:官方的演示 Demo 也有问题 😂。

其实问题就是在 没有显式地写出关闭标签……

阅读全文

Set & Map 数据结构是无法被 Vue 监听的

这次在写业务的时候因为是无限层级的递归表单,用了 provide/inject 来暴露注册以便收集数据。所以就想要用 Map 数据结构来处理数据的收集等等功能。直接使用 记录ID 作为键名就可以了,这样也可以直接去重。但是写完了业务代码之后发现我把后代的表单注册进来并没有触发响应,导致数据回填失败。

所以想着是不是 Vue 2x 无法监听 Map 或者 Set 的数据变更的。就去检索了一下相关的信息,发现 Vue 2x 真的无法监听 Map 以及 Set 俩兄弟。只能够通过修改其他变量来曲线救国。

Vue 3x 通过 Proxy 来代理就没有了这个问题。

阅读全文

Vue 中的样式穿透 v-deep、/deep/ 和 >>>

Vue 项目的开发中,很多人都因为想要限制 CSS 样式的作用范围(避免样式污染的问题)去使用 scope 属性。

但是很多的情况下都会去修改分装好的子组件以及UI库中的组件样式,所以经常会用到 样式穿透 这个东西,因为我以前是使用的 Stylus 作为样式预处理器的,所以并没有感觉到什么困惑的地方,但是有很多同学是使用的 Scss 以及 Less 的,对于他们来说什么时候使用 /deep/ 什么时候使用 ::v-deep 是很困扰的。特别是对于一些刚刚进入前端圈的小伙伴们。

正好最近在思否也遇到了很多人来问这样的问题,就像一次性都把相关的疑问都回答了。

阅读全文

Vue中接收没有声明的Prop属性[null/undefined]的接收问题

最近在写基础组件,同事一直反馈说组件总是提示警告:

[Vue warn]: Invalid prop: type check failed for prop "value". Expected String, Array, got Null

一开始以为是接收的问题,把定义的props加上了工厂函数后没有报异常就没再管了。
今天再去看的时候发现还是有报错,检查了一下组件代码没发现问题,在查看业务代码的时候发现同事喜欢给声明的变量默认赋值为 null。而不是声明正确的基础类型。所以我就想应该如何把这个问题彻底解决掉。

🔔 其实这个提示为了提醒可能你绑定的变量并不一定存在。

阅读全文

聊一个复用组件中使用debounce时遇到的问题

今天我中遇到了一个这样的场景,发现触发复用的自定义组件中添加了防抖的函数,发现只执行了一次,并没有如预期的那样每个组件内的函数都执行一次。

一开始以为是没有同步赋值,检查了一下没问题,才把关注点转移到 debounce 上面。移除防抖之后果然解决问题了,但防抖又不能去去掉。

所以查了一下相关的问题,发现是因为多个组件实例是共享同一个预置防抖的函数,并不是相互独立的。

阅读全文

AntD of Vue 中 <AForm> 表单域组件化使用的尝试

最近有一个项目,我发现有一些表单内容高度重复的情况,几张页面的表单虽有些细微差,但还是有很多同样的表单内容,或者 表单域A表单域B 同时出现在一个页面中的这种情况。

我就想着能不能把他们都提出来,单独的做成组件在再使用到这些内容的时直接引入对应的表单域组件,并且可以把下拉菜单的远程查询也放到组件中,这样就会精简点很多重复的代码。

阅读全文

Provide/Inject - 我在Vue中很少使用到的一种父子通讯方式

也算是经典面试题的一部分了,对于父子间的通讯很多时候的使用我都是限于 props/$emit 来处理,或者 Vuex/EventBus 这种方式,很少会用到 Provide/Inject 来处理。其实这是一个很实用的跨级组件间通讯的方式。

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。

看文档中关于这对API的解释就可以看到,向其所有后代 注入一个依赖,所以在跨级组件间通讯,或者 单父多子组件间通讯就会很方便了。

简单的使用可以查看官方文档中的示例,我就不举例了,因为使用起来真的很简单。

最直白的(但是错误的)可以理解为 props 的强化版本,暴露一个可以无视子组件的嵌套层级属性来进行注入。

阅读全文

VueJS 的过滤器 filter API

一直没有怎么用过 Vue 的 过滤器 API,都是直接用 AntD Pro 当中提供的数字千分格式化、时间格式化之类的,没有自己去声明过,主要是因为 Array.prototype.filter 的先入为主,一直把 vue.filter 理解成为了筛选,而不是过滤器。

其实,vue.filter 是借鉴了 Linux 当中的 Pipe 符号 (|) 来处理数据 ,然后借用了 filter 这个名字:

利用 Linux 所提供的管道符 “|” 将两个命令隔开,管道符左边命令的输出就会作为管道符右边命令的输入

其实我觉得如果直接用 pipe 来命名其实就更好理解了,但是也许是因为前端圈子接触到 pipe 的人并不多,使用 filter 这个熟悉的单词可能更加容易让大众接受。

使用起来确实很方便,用 | 符号分隔就行,会按照 从前往后的顺序 依次 传入过滤器,然后返回转换后的值。

等到后来再遇到适合的场景想起来使用 filter ,但又因为项目的历史原因没有去使用,因为自己都是局部使用 computed计算方法调用返回 来处理(也是Vue3所推荐的替代过滤器的方式

阅读全文