index.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. import XEUtils from 'xe-utils';
  2. import { renderer, getComponent } from '../../ui';
  3. import { getOnName, getModelEvent, getChangeEvent } from '../../ui/src/vn';
  4. import { errLog } from '../../ui/src/log';
  5. const componentDefaultModelProp = 'value';
  6. /**
  7. * 已废弃
  8. * @deprecated
  9. */
  10. function getOldComponentName(name) {
  11. return `vxe-${`${name || ''}`.replace('$', '')}`;
  12. }
  13. /**
  14. * 已废弃
  15. * @deprecated
  16. */
  17. function getOldComponent({ name }) {
  18. return getOldComponentName(name);
  19. }
  20. function getDefaultComponent({ name }) {
  21. return getComponent(name) || name;
  22. }
  23. function getNativeAttrs(renderOpts) {
  24. let { name, attrs } = renderOpts;
  25. if (name === 'input') {
  26. attrs = Object.assign({ type: 'text' }, attrs);
  27. }
  28. return attrs;
  29. }
  30. function getComponentFormItemProps(renderOpts, params, value, defaultProps) {
  31. return XEUtils.assign({}, defaultProps, renderOpts.props, { [componentDefaultModelProp]: value });
  32. }
  33. /**
  34. * 原生事件处理
  35. * @param renderOpts
  36. * @param params
  37. * @param modelFunc
  38. * @param changeFunc
  39. */
  40. function getElementOns(renderOpts, params, modelFunc, changeFunc) {
  41. const { events } = renderOpts;
  42. const modelEvent = getModelEvent(renderOpts);
  43. const changeEvent = getChangeEvent(renderOpts);
  44. const isSameEvent = changeEvent === modelEvent;
  45. const ons = {};
  46. if (events) {
  47. XEUtils.objectEach(events, (func, key) => {
  48. ons[getOnName(key)] = function (...args) {
  49. func(params, ...args);
  50. };
  51. });
  52. }
  53. if (modelFunc) {
  54. ons[getOnName(modelEvent)] = function (targetEvnt) {
  55. modelFunc(targetEvnt);
  56. if (isSameEvent && changeFunc) {
  57. changeFunc(targetEvnt);
  58. }
  59. if (events && events[modelEvent]) {
  60. events[modelEvent](params, targetEvnt);
  61. }
  62. };
  63. }
  64. if (!isSameEvent && changeFunc) {
  65. ons[getOnName(changeEvent)] = function (...args) {
  66. changeFunc(...args);
  67. if (events && events[changeEvent]) {
  68. events[changeEvent](params, ...args);
  69. }
  70. };
  71. }
  72. return ons;
  73. }
  74. /**
  75. * 组件事件处理
  76. * @param renderOpts
  77. * @param params
  78. * @param modelFunc
  79. * @param changeFunc
  80. */
  81. function getComponentOns(renderOpts, params, eFns, eventOns) {
  82. const { events } = renderOpts;
  83. const { model: modelFunc, change: changeFunc } = eFns || {};
  84. const modelEvent = getModelEvent(renderOpts);
  85. const changeEvent = getChangeEvent(renderOpts);
  86. const ons = {};
  87. XEUtils.objectEach(events, (func, key) => {
  88. ons[getOnName(key)] = function (...args) {
  89. if (!XEUtils.isFunction(func)) {
  90. errLog('vxe.error.errFunc', [`[form] ${func}`]);
  91. }
  92. func(params, ...args);
  93. };
  94. });
  95. if (modelFunc) {
  96. ons[getOnName(modelEvent)] = function (targetEvnt) {
  97. modelFunc(targetEvnt);
  98. if (events && events[modelEvent]) {
  99. events[modelEvent](params, targetEvnt);
  100. }
  101. };
  102. }
  103. if (changeFunc) {
  104. ons[getOnName(changeEvent)] = function (...args) {
  105. changeFunc(...args);
  106. if (events && events[changeEvent]) {
  107. events[changeEvent](params, ...args);
  108. }
  109. };
  110. }
  111. return eventOns ? Object.assign(ons, eventOns) : ons;
  112. }
  113. function getItemOns(renderOpts, params) {
  114. const { $form, data, field } = params;
  115. return getComponentOns(renderOpts, params, {
  116. model(value) {
  117. // 处理 model 值双向绑定
  118. XEUtils.set(data, field, value);
  119. },
  120. change() {
  121. // 处理 change 事件相关逻辑
  122. $form.updateStatus(params);
  123. }
  124. });
  125. }
  126. function getNativeItemOns(renderOpts, params) {
  127. const { $form, data, field } = params;
  128. return getElementOns(renderOpts, params, (evnt) => {
  129. // 处理 model 值双向绑定
  130. const itemValue = evnt.target.value;
  131. XEUtils.set(data, field, itemValue);
  132. }, () => {
  133. // 处理 change 事件相关逻辑
  134. $form.updateStatus(params);
  135. });
  136. }
  137. function renderNativeOptgroup(h, renderOpts, params, renderOptionsMethods) {
  138. const { optionGroups, optionGroupProps = {} } = renderOpts;
  139. const groupOptions = optionGroupProps.options || 'options';
  140. const groupLabel = optionGroupProps.label || 'label';
  141. if (optionGroups) {
  142. return optionGroups.map((group, gIndex) => {
  143. return h('optgroup', {
  144. key: gIndex,
  145. attrs: {
  146. label: group[groupLabel]
  147. }
  148. }, renderOptionsMethods(group[groupOptions], renderOpts, params));
  149. });
  150. }
  151. return [];
  152. }
  153. /**
  154. * 渲染表单-项
  155. * 用于渲染原生的标签
  156. */
  157. function nativeItemRender(h, renderOpts, params) {
  158. const { data, field } = params;
  159. const { name } = renderOpts;
  160. const attrs = getNativeAttrs(renderOpts);
  161. const itemValue = XEUtils.get(data, field);
  162. return [
  163. h(`${name}`, {
  164. class: `vxe-default-${name}`,
  165. attrs,
  166. domProps: {
  167. value: attrs && name === 'input' && (attrs.type === 'submit' || attrs.type === 'reset') ? null : itemValue
  168. },
  169. on: getNativeItemOns(renderOpts, params)
  170. })
  171. ];
  172. }
  173. function defaultItemRender(h, renderOpts, params) {
  174. const { data, field } = params;
  175. const itemValue = XEUtils.get(data, field);
  176. return [
  177. h(getDefaultComponent(renderOpts), {
  178. props: getComponentFormItemProps(renderOpts, params, itemValue),
  179. on: getItemOns(renderOpts, params)
  180. })
  181. ];
  182. }
  183. /**
  184. * 已废弃
  185. * @deprecated
  186. */
  187. function oldItemRender(h, renderOpts, params) {
  188. const { data, field } = params;
  189. const itemValue = XEUtils.get(data, field);
  190. return [
  191. h(getOldComponent(renderOpts), {
  192. props: getComponentFormItemProps(renderOpts, params, itemValue),
  193. on: getItemOns(renderOpts, params)
  194. })
  195. ];
  196. }
  197. /**
  198. * 已废弃
  199. * @deprecated
  200. */
  201. function oldButtonItemRender(h, renderOpts, params) {
  202. return [
  203. h('vxe-button', {
  204. props: getComponentFormItemProps(renderOpts, params, null),
  205. on: getComponentOns(renderOpts, params)
  206. })
  207. ];
  208. }
  209. /**
  210. * 已废弃
  211. * @deprecated
  212. */
  213. function oldButtonsItemRender(h, renderOpts, params) {
  214. const { children } = renderOpts;
  215. return children ? children.map((childRenderOpts) => oldButtonItemRender(h, childRenderOpts, params)[0]) : [];
  216. }
  217. /**
  218. * 渲染原生的 select 标签
  219. */
  220. function renderNativeFormOptions(h, options, renderOpts, params) {
  221. const { data, field } = params;
  222. const { optionProps = {} } = renderOpts;
  223. const labelProp = optionProps.label || 'label';
  224. const valueProp = optionProps.value || 'value';
  225. const disabledProp = optionProps.disabled || 'disabled';
  226. const cellValue = XEUtils.get(data, field);
  227. if (options) {
  228. return options.map((item, oIndex) => {
  229. return h('option', {
  230. key: oIndex,
  231. props: {
  232. value: item[valueProp],
  233. disabled: item[disabledProp],
  234. /* eslint-disable eqeqeq */
  235. selected: item[valueProp] == cellValue
  236. }
  237. }, item[labelProp]);
  238. });
  239. }
  240. return [];
  241. }
  242. /**
  243. * 渲染表单-项
  244. */
  245. function defaultFormItemRender(h, renderOpts, params) {
  246. const { data, field } = params;
  247. const itemValue = XEUtils.get(data, field);
  248. return [
  249. h(getDefaultComponent(renderOpts), {
  250. props: getComponentFormItemProps(renderOpts, params, itemValue),
  251. on: getItemOns(renderOpts, params)
  252. })
  253. ];
  254. }
  255. function formItemRadioAndCheckboxRender(h, renderOpts, params) {
  256. const { options, optionProps } = renderOpts;
  257. const { data, field } = params;
  258. const itemValue = XEUtils.get(data, field);
  259. return [
  260. h(getDefaultComponent(renderOpts), {
  261. props: Object.assign({ options,
  262. optionProps }, getComponentFormItemProps(renderOpts, params, itemValue)),
  263. on: getItemOns(renderOpts, params)
  264. })
  265. ];
  266. }
  267. /**
  268. * 已废弃
  269. * @deprecated
  270. */
  271. function oldFormItemRadioAndCheckboxRender(h, renderOpts, params) {
  272. const { name, options, optionProps = {} } = renderOpts;
  273. const { data, field } = params;
  274. const labelProp = optionProps.label || 'label';
  275. const valueProp = optionProps.value || 'value';
  276. const disabledProp = optionProps.disabled || 'disabled';
  277. const itemValue = XEUtils.get(data, field);
  278. const compName = getOldComponentName(name);
  279. // 如果是分组
  280. if (options) {
  281. return [
  282. h(`${compName}-group`, {
  283. props: getComponentFormItemProps(renderOpts, params, itemValue),
  284. on: getItemOns(renderOpts, params),
  285. scopedSlots: {
  286. default: () => {
  287. return options.map((item, index) => {
  288. return h(compName, {
  289. key: index,
  290. props: {
  291. label: item[valueProp],
  292. content: item[labelProp],
  293. disabled: item[disabledProp]
  294. }
  295. });
  296. });
  297. }
  298. }
  299. })
  300. ];
  301. }
  302. return [
  303. h(compName, {
  304. props: getComponentFormItemProps(renderOpts, params, itemValue),
  305. on: getItemOns(renderOpts, params)
  306. })
  307. ];
  308. }
  309. /**
  310. * 表单 - 渲染器
  311. */
  312. renderer.mixin({
  313. input: {
  314. formItemAutoFocus: 'input',
  315. renderFormItemContent: nativeItemRender
  316. },
  317. textarea: {
  318. formItemAutoFocus: 'textarea',
  319. renderFormItemContent: nativeItemRender
  320. },
  321. select: {
  322. formItemAutoFocus: 'input',
  323. renderFormItemContent(h, renderOpts, params) {
  324. return [
  325. h('select', {
  326. class: 'vxe-default-select',
  327. attrs: Object.assign({}, getNativeAttrs(renderOpts)),
  328. on: getNativeItemOns(renderOpts, params)
  329. }, renderOpts.optionGroups ? renderNativeOptgroup(h, renderOpts, params, renderNativeFormOptions) : renderNativeFormOptions(h, renderOpts.options, renderOpts, params))
  330. ];
  331. }
  332. },
  333. VxeInput: {
  334. formItemAutoFocus: 'input',
  335. renderFormItemContent: defaultItemRender
  336. },
  337. VxeNumberInput: {
  338. formItemAutoFocus: 'input',
  339. renderFormItemContent: defaultItemRender
  340. },
  341. VxePasswordInput: {
  342. formItemAutoFocus: 'input',
  343. renderFormItemContent: defaultItemRender
  344. },
  345. VxeTextarea: {
  346. formItemAutoFocus: 'textarea',
  347. renderFormItemContent: defaultItemRender
  348. },
  349. VxeDatePicker: {
  350. formItemAutoFocus: 'input',
  351. renderFormItemContent: defaultItemRender
  352. },
  353. VxeDateRangePicker: {
  354. formItemAutoFocus: 'input',
  355. renderFormItemContent(h, renderOpts, params) {
  356. const { startField, endField } = renderOpts;
  357. const { $form, data, field } = params;
  358. const itemValue = XEUtils.get(data, field);
  359. const seProps = {};
  360. const seOs = {};
  361. if (startField && endField) {
  362. seProps.startValue = XEUtils.get(data, startField);
  363. seProps.endValue = XEUtils.get(data, endField);
  364. seOs['update:startValue'] = (value) => {
  365. if (startField) {
  366. XEUtils.set(data, startField, value);
  367. }
  368. };
  369. seOs['update:endValue'] = (value) => {
  370. if (endField) {
  371. XEUtils.set(data, endField, value);
  372. }
  373. };
  374. }
  375. return [
  376. h(getDefaultComponent(renderOpts), {
  377. props: getComponentFormItemProps(renderOpts, params, itemValue, seProps),
  378. on: getComponentOns(renderOpts, params, {
  379. model(value) {
  380. // 处理 model 值双向绑定
  381. XEUtils.set(data, field, value);
  382. },
  383. change() {
  384. // 处理 change 事件相关逻辑
  385. $form.updateStatus(params);
  386. }
  387. }, seOs)
  388. })
  389. ];
  390. }
  391. },
  392. VxeButton: {
  393. renderFormItemContent: defaultFormItemRender
  394. },
  395. VxeButtonGroup: {
  396. renderFormItemContent(h, renderOpts, params) {
  397. const { options } = renderOpts;
  398. const { data, field } = params;
  399. const itemValue = XEUtils.get(data, field);
  400. return [
  401. h(getDefaultComponent(renderOpts), {
  402. props: Object.assign({ options }, getComponentFormItemProps(renderOpts, params, itemValue)),
  403. on: getItemOns(renderOpts, params)
  404. })
  405. ];
  406. }
  407. },
  408. VxeSelect: {
  409. formItemAutoFocus: 'input',
  410. renderFormItemContent(h, renderOpts, params) {
  411. const { data, field } = params;
  412. const { options, optionProps, optionGroups, optionGroupProps } = renderOpts;
  413. const itemValue = XEUtils.get(data, field);
  414. return [
  415. h(getDefaultComponent(renderOpts), {
  416. props: getComponentFormItemProps(renderOpts, params, itemValue, { options, optionProps, optionGroups, optionGroupProps }),
  417. on: getItemOns(renderOpts, params)
  418. })
  419. ];
  420. }
  421. },
  422. VxeTreeSelect: {
  423. formItemAutoFocus: 'input',
  424. renderFormItemContent(h, renderOpts, params) {
  425. const { data, field } = params;
  426. const { options, optionProps } = renderOpts;
  427. const itemValue = XEUtils.get(data, field);
  428. return [
  429. h(getDefaultComponent(renderOpts), {
  430. props: getComponentFormItemProps(renderOpts, params, itemValue, { options, optionProps }),
  431. on: getItemOns(renderOpts, params)
  432. })
  433. ];
  434. }
  435. },
  436. VxeTableSelect: {
  437. formItemAutoFocus: 'input',
  438. renderFormItemContent(h, renderOpts, params) {
  439. const { data, field } = params;
  440. const { options, optionProps } = renderOpts;
  441. const itemValue = XEUtils.get(data, field);
  442. return [
  443. h(getDefaultComponent(renderOpts), {
  444. props: getComponentFormItemProps(renderOpts, params, itemValue, { options, optionProps }),
  445. on: getItemOns(renderOpts, params)
  446. })
  447. ];
  448. }
  449. },
  450. VxeColorPicker: {
  451. formItemAutoFocus: 'input',
  452. renderFormItemContent(h, renderOpts, params) {
  453. const { data, field } = params;
  454. const { options } = renderOpts;
  455. const itemValue = XEUtils.get(data, field);
  456. return [
  457. h(getDefaultComponent(renderOpts), {
  458. props: getComponentFormItemProps(renderOpts, params, itemValue, { colors: options }),
  459. on: getItemOns(renderOpts, params)
  460. })
  461. ];
  462. }
  463. },
  464. VxeIconPicker: {
  465. formItemAutoFocus: 'input',
  466. renderFormItemContent(h, renderOpts, params) {
  467. const { data, field } = params;
  468. const { options } = renderOpts;
  469. const itemValue = XEUtils.get(data, field);
  470. return [
  471. h(getDefaultComponent(renderOpts), {
  472. props: getComponentFormItemProps(renderOpts, params, itemValue, { icons: options }),
  473. on: getItemOns(renderOpts, params)
  474. })
  475. ];
  476. }
  477. },
  478. VxeRadio: {
  479. renderFormItemContent: defaultFormItemRender
  480. },
  481. VxeRadioGroup: {
  482. renderFormItemContent: formItemRadioAndCheckboxRender
  483. },
  484. VxeCheckbox: {
  485. renderFormItemContent: defaultFormItemRender
  486. },
  487. VxeCheckboxGroup: {
  488. renderFormItemContent: formItemRadioAndCheckboxRender
  489. },
  490. VxeSwitch: {
  491. renderFormItemContent: defaultItemRender
  492. },
  493. VxeRate: {
  494. renderFormItemContent: defaultItemRender
  495. },
  496. VxeSlider: {
  497. renderFormItemContent: defaultItemRender
  498. },
  499. VxeImage: {
  500. renderFormItemContent(h, renderOpts, params) {
  501. const { data, field } = params;
  502. const { props } = renderOpts;
  503. const itemValue = XEUtils.get(data, field);
  504. return [
  505. h(getDefaultComponent(renderOpts), {
  506. props: Object.assign(Object.assign({}, props), { src: itemValue }),
  507. on: getItemOns(renderOpts, params)
  508. })
  509. ];
  510. }
  511. },
  512. VxeImageGroup: {
  513. renderFormItemContent(h, renderOpts, params) {
  514. const { data, field } = params;
  515. const { props } = renderOpts;
  516. const itemValue = XEUtils.get(data, field);
  517. return [
  518. h(getDefaultComponent(renderOpts), {
  519. props: Object.assign(Object.assign({}, props), { urlList: itemValue }),
  520. on: getItemOns(renderOpts, params)
  521. })
  522. ];
  523. }
  524. },
  525. VxeUpload: {
  526. renderFormItemContent: defaultItemRender
  527. },
  528. // 以下已废弃
  529. $input: {
  530. formItemAutoFocus: 'input',
  531. renderFormItemContent: oldItemRender
  532. },
  533. $textarea: {
  534. formItemAutoFocus: 'textarea',
  535. renderFormItemContent: oldItemRender
  536. },
  537. $button: {
  538. renderFormItemContent: oldButtonItemRender
  539. },
  540. $buttons: {
  541. renderFormItemContent: oldButtonsItemRender
  542. },
  543. $select: {
  544. formItemAutoFocus: 'input',
  545. renderFormItemContent(h, renderOpts, params) {
  546. const { data, field } = params;
  547. const { options, optionProps, optionGroups, optionGroupProps } = renderOpts;
  548. const itemValue = XEUtils.get(data, field);
  549. return [
  550. h(getOldComponent(renderOpts), {
  551. props: getComponentFormItemProps(renderOpts, params, itemValue, { options, optionProps, optionGroups, optionGroupProps }),
  552. on: getItemOns(renderOpts, params)
  553. })
  554. ];
  555. }
  556. },
  557. $radio: {
  558. renderFormItemContent: oldFormItemRadioAndCheckboxRender
  559. },
  560. $checkbox: {
  561. renderFormItemContent: oldFormItemRadioAndCheckboxRender
  562. },
  563. $switch: {
  564. renderFormItemContent: oldItemRender
  565. }
  566. // 以上已废弃
  567. });