Vue.js 将数据从插槽传递到组件实例

新手上路,请多包涵

我正在尝试构建一个可重用的组件来处理使用 Vue.js 通过 AJAX 提交表单。理想情况下,我想要做的是有一个通用组件,可以用来代替 HTML form 元素,其中可能包含一组未知的表单元素,例如 inputselect , textarea 等等。

我的组件有以下代码,名为 ajax-form

 <template>
    <form class="form" :action="action" :method="method" v-on:submit.prevent="ajaxSubmit">
        <slot></slot>
    </form>
</template>

<script>
module.exports = {
    props: {
        action: {
            required: true,
            type: String
        },
        method: {
            default: 'post',
            required: false,
            type: String
        }
    },
    data() {
        return {
            formData: {}
        }
    },
    methods: {
        ajaxSubmit() {
            // Do ajax
        }
    }
}
</script>

在我的 HTML 中,我会有如下内容:

 <ajax-form action="http://example.com/do/something">
    <input name="first_name" type="text">
    <textarea name="about_you"></textarea>
</ajax-form>

我最希望发生的事情是使用它的插槽将所有放置在我的组件内的表单元素映射到我的 Vue 组件实例中的 data.formData 属性。所以在这种情况下, data 属性看起来像:

 data: {
    formData: {
        first_name: '',
        about: ''
    }
}

如果我要在我的 HTML 中向组件添加另一个字段,我希望它也能映射到 Vue 实例的 data 属性。

有什么办法可以做到这一点?有没有一种方法可以告诉 Vue,当我通过插槽将表单元素放入组件时,我希望将此元素映射到组件的 data 中的某些内容?

我尝试在每个表单元素上添加 v-modelv-bind 以查看它是否会以某种方式将数据传递到组件的数据中:

 <ajax-form action="http://example.com/do/something">
    <input name="first_name" type="text" v-model="formData.first_name">
</ajax-form>

但是,Vue 抱怨反应式数据属性必须在模板中使用之前声明:

[Vue 警告]:属性或方法“formData”未在实例上定义,但在渲染期间被引用。确保在数据选项中声明响应式数据属性。

原文由 Jonathon 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 542
2 个回答

你不能做你要求的事情,因为插槽范围仅限于父范围。

您可以在全局 Vue 实例上定义 formData,因此现在可以从父范围访问它。

 const app = new Vue({
    el: '#app',
    data: {
        formData : {}
    }
});

现在你可以将它作为 prop 传递给表单:

 <ajax-form action="#" :form-data="formData>
    <input name="first_name" type="text" v-model="formData.first_name">
</ajax-form>

原文由 Goodbytes 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以使用 scopedSlots 来做到这一点。

api 看起来像这样:

 <ajax-form action="http://example.com/do/something">
   <template scope="{formData}">
   <input name="first_name" type="text" v-model="formData.first_name">
   </template>
</ajax-form>

ajax-form 组件中:

 <form class="form" :action="action" :method="method" v-on:submit.prevent="ajaxSubmit">
   <slot :formData="formData">
</form>

原文由 blockhead 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题