vitejs / vite-plugin-vue2-jsx

Vite plugin for Vue 2.7 JSX support
MIT License
58 stars 6 forks source link

How to use v-model in vue2.7 jsx #7

Open Mr-xzq opened 1 year ago

Mr-xzq commented 1 year ago
// package.json
{
  "dependencies": {
    "vue": "~2.7.8",
  },
  "devDependencies": {
    "@babel/core": "^7.18.10",
    "@vitejs/plugin-legacy": "~2.0.0",
    "@vitejs/plugin-vue2": "^1.1.2",
    "@vitejs/plugin-vue2-jsx": "^1.0.2",
    "terser": "^5.14.2",
    "vite": "~3.0.3",
  },
  "engines": {
    "node": "^16.0.0",
    "pnpm": "^7.9.0"
  },

}
// vite.config.js
import { defineConfig } from 'vite';
import legacy from '@vitejs/plugin-legacy';
import vue2 from '@vitejs/plugin-vue2';
import vue2Jsx from '@vitejs/plugin-vue2-jsx';

export default defineConfig(({ command, mode }) => {
  return {
    plugins: [
      vue2(),
      vue2Jsx(),
      legacy({
        // When targeting IE11, you also need regenerator-runtime
        additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
      }),
    ],
  };
});
// demo.vue
<script lang="jsx">
import { defineComponent, ref } from 'vue';

let index = 0;
export default defineComponent({
  setup() {

    const date1 = ref(new Date());

    // Invalid prop: type check failed for prop "value". Expected Date, String, Array, got Object 
    const datePicker1 = <DatePicker  v-model={date1}></DatePicker>;

    const date2 = new Date()
    // Although there is no warning above, but this loses reactive
    const datePicker2 = <DatePicker  v-model={date2}></DatePicker>;

    const date3 = ref(new Date());
    // [plugin:vite:vue2-jsx] unknown: Cannot read properties of undefined (reading 'body')
    const datePicker3 = <DatePicker  v-model={date3.value}></DatePicker>;

    return () => datePicker;
  },
});
</script>
emosheeep commented 1 year ago

Actions to access .value should be written in render function, which makes vue properly collect deps. Try to change your code as below:

export default defineComponent({
  setup() {
    const date3 = ref(new Date());
    return () =>  <DatePicker  v-model={date3.value}></DatePicker>;
  },
});
Mr-xzq commented 1 year ago

Actions to access .value should be written in render function, which makes vue properly collect deps. Try to change your code as below:

export default defineComponent({
  setup() {
    const date3 = ref(new Date());
    return () =>  <DatePicker  v-model={date3.value}></DatePicker>;
  },
});

Thanks for your help, your answer resolve my problem.

https://stackblitz.com/edit/vitejs-vite-rmxqpw?file=src/App.vue

vue2 7-jsx-setup-render

Mr-xzq commented 1 year ago

https://github.com/vitejs/vite-plugin-vue2-jsx/issues/7#issuecomment-1242589032

demo code

image

zehuichan commented 1 year ago

@Mr-xzq 我也遇到了,咋解决

zehuichan commented 1 year ago

https://stackblitz.com/edit/vitejs-vite-sanfhk?file=package.json

Mr-xzq commented 1 year ago

@zehuichan

v-model 的本质就是一个语法糖

一个组件上的 v-model 默认会利用名为 valueprop 和名为 input 的事件; 但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的model 选项可以用来避免这样的冲突;

这是我一个临时的解决方案:https://stackblitz.com/edit/vitejs-vite-hocdde?file=src/components/FormItem.vue

<script lang="jsx">
import { defineComponent, computed, ref } from 'vue';
export default defineComponent({
  name: 'FormItem',
  inheritAttrs: false,
  props: ['value'],
  emits: ['input'],
  setup(props, { emit }) {
    return () => {
      return (
        <el-input
          value={props.value}
          vOn:input={(val) => emit('input', val)}
          clearable
          placeholder="请输入"
        />
      );
    };
  },
});
</script>
zehuichan commented 1 year ago

@Mr-xzq 感谢解答