<form>内部项目适合切组件吗?
发布于 8 个月前 作者 banyungong 432 次浏览 来自 问答
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

对于使用Vue表单有一些疑问:

  1. < form >内部项目适合分离出组件吗?

今天专案有一个表单,如下图:

  • 每个项目的input/select/textarea都有各自的标题、错误消息、id、name,
  • 每个组合有可能1~5个项目(input/select/textarea)组成,每个组合都有各自的Icon
  • 每个项目(input/select/textarea)操作都会影响该组合的icon

form_question

这样的表单,单组合适合分离出component吗?
会想分离成component是因为需要为每个设置data值:focus: false

照上述需求,分离出一个有两项目的组合就30行
(使用Pug、bootstrap vue、vuelidate验证)

  1. 如果页面上有完全一样的表单,会同时出现,这样要如何自动带变量给component?
    (用来更改内部组件id)
    会出现在不同区块,不能用v-for带index值
    还是只能手动调整带入的index值?
    类似v-bine-index=‘1’、v-bine-index='2’之类
8 回复

完全不拆分组件,本不相关的状态和逻辑就会耦合在一起,增加心智的负担;
拆分组件过细,原本相关的状态和逻辑就会分散到多处,增加记忆的负担。

该不该拆分组件、应该怎么拆,就是在这两个极端之间做平衡取舍,取自己最能接受的程度即可。

另外,如果有大量动态生成元素的需求(而不是在既定的元素组合——也就是模板——之间通过固定条件做选择),可以考虑 JSX。

文字使用不正确,造成不舒服感到很抱歉。
已修正询问内文,下次会注意的。

如果就一个项目在用,那自然是不用封装成组件啦。

如果有多个项目都在用这种表单,且存在拷贝粘贴拷贝粘贴拷贝粘贴这种繁琐的劳动量的时候呢,就需要考虑封装一个通用性组件啦。

嗯,这两者的确各有优势,不过我在实际复杂的表单(需要写多个v-if进行条件判断,多个组件组合之类的)开发中,还是习惯JSX更多一些,当然如果比较简单的表单(那种能一个v-if或者v-for搞定的),我更倾向于不使用JSX,直接用vue的指令去搞定。

假设你的数据结构是:

{
  a: {
    b: {
      c: 111,
    },
  },
}

你对 a/b/c 赋值,当你的循环执行到最后一遍时,targetKey 是什么?

targetKey预计要是key值,如a.b.c。

有尝试改用Vue.set(),有成功update,但如果把值绑在radio上,就会出现多次更新。
页面上有几个就更新几次。

updateValue (state, { key, val }) {
	console.log('updateValue');

	const keySplit = key.split('/');

	let targetKey = state;

	for (let i = 0; i < keySplit.length - 1; i++) {
		const currentKey = targetKey[keySplit[i]];
		targetKey = currentKey;
	}

	Vue.set(targetKey, keySplit[keySplit.length - 1], val);
},

JSX或Vue本身的架构验证方式应该可行,现在有另外一个产生的问题:数据绑定。


因为在不同的Component,绑值通过Vuex另外就是双向绑定的值,因为所有的input都在不同层级的Component内,所以想说绑定的值都使用Store(Vuex)的方式去取值、更新值。

数据结构是长这样,要取值、推值的部分层级不一定一样:

state = {
	a1: {
		b1: {
			c1: null
			...以下N个
		}
		...以下N个
		b2: null
	}
	...以下N个
}

内部推值的data形式

// component 内部
data = {
	key: 'a1/b1/c1'
	val: 'Name'
}
this.$store.commit('changeValue', data);

想说尝试使用跑循环找key值再推值,不晓得为什幺没用,也没有报错。

mutations: {
	changeValue (state, { key, val }){
		const keySplit = key.split('/');

		let targetKey = state;

		for (let i = 0; i < keySplit.length; i++) {
			const currentKey = targetKey[keySplit[i]];
			targetKey = currentKey;
		}

		targetKey = val;
	}
}

key、val取的值是对的,targetKey抓到的值也是对的,但 “targetKey = val” 就是没用。

不过如果这样做负担会不会太大?
keyup, blur就更新值,一直跑循环,但好像也没有其它比较好的方式?

声明式 vs 半命令式(JSX 倒也不能完全算命令式)的区别。只能说各有利弊吧。

在 v-if 之外,Vue 还提供了 <component>,其实也可以解决部分动态模板需求。只是模板毕竟是模板,灵活性比不上 render 函数。所以这也是个取舍吧。

PS: 但模板可以搞语法糖(doge)。而且 Vue 3.x 支持模板编译提示,我还是挺模板(doge x2)。

回到顶部