动态添加属性到Vue组件

时间:2017-01-26 00:13:08

标签: vue.js vuejs2 vue-component

我从数据库加载数据,驱动我显示的组件类型

AJAX调用关闭并返回一些数据(如果需要,可以重新构建)

{
  component_type: 'list-item',
  props: {
    name: 'test',
    value: 'some value'
  }
}

在我的父对象上可以访问一个名为 component

的变量

在我的父对象的模板中,我有以下

<component :is="component.component_type" ></component>

这样可以正常工作并按预期加载组件。

接下来我想将我的数据对象中的属性添加到此标记中

<component :is="component.component_type" {{ component.props }} ></component>

这不起作用,拒绝使用 {{>来编写代码。我认为这是浏览器抛出的错误,而不是Vue,尽管我不确定。

作为参考,我希望输出看起来像:

<component :is="component.component_type" name='test' value='some value' ></component>

我怎样才能传递这些属性?理想情况下,我希望将这些与父母的数据/道具联系起来,以便在数据库中轻松更改它们,并且UI会相应地更改。

最糟糕的是,我会在服务器端生成所有内容,但我宁愿通过ajax来做,因为我目前正在尝试这样做。

3 个答案:

答案 0 :(得分:5)

如果有人想知道如何使用Vue 2执行此操作,您只需将对象传递给v-bind:

<template>
    <component :is="componentType" v-bind="props"></component>
</template>

<script>
    export default {
        data() {
            return {
                componentType: 'my-component',
                props: {
                    foo: 'foofoo',
                    bar: 'barbar'
                }
            }
        }
    }
</script>

答案 1 :(得分:4)

thread之后,我看到了两个选项。

一个是传递一个对象本身就是一个对象,并传递其中可以由子组件使用的所有相关键值,如下所示:

<component :is="component. component_type"
        :options="component.props"
</component>

提到的其他解决方案是有一个指令,你传递对象,它会将该对象中的键属性设置为相应的值,你可以在工作here中看到这一点。

Vue.directive('props', {
        priority: 3000,
    bind() {

        // set the last component child as the current
        let comp = this.vm.$children[this.vm.$children.length - 1];
        let values = null;
        if(this._scope && this._scope.$eval) {
            values = this._scope.$eval(this.expression);
        } else {
            values = this.vm.$eval(this.expression);
        }
        if(typeof values !== 'object' || values instanceof Array) {
            values = { data: values };
        }

        // apply properties to component data
        for(let key in values) {
            if(values.hasOwnProperty(key)) {
                let hkey = this.hyphenate(key);
                let val = values[key];
                if(typeof val === 'string') {
                    comp.$options.el.setAttribute(hkey, values[key]);
                } else {
                    comp.$options.el.setAttribute(':' + hkey, values[key]);
                }
            }
        }

                console.log(comp.$options.el.outerHTML);
        comp._initState();
    },

    /*
     * Hyphenate a camelCase string.
     */
    hyphenate(str) {
        let hyphenateRE = /([a-z\d])([A-Z])/g;
        return str.replace(hyphenateRE, '$1-$2').toLowerCase();
    }
});

并像这样使用它:

<div class="app">
    <component is="component.component_type" v-props="component.props"></component>
</div>

答案 2 :(得分:3)

据我所知,Vue.js模板中没有其他道具(传播道具)语法。

可能的解决方案是渲染功能。使用渲染函数时,您可以充分利用JavaScript,因此您可以执行以下操作:

namespace SerialCommunicationsTest
{
    class Program
    {
        static UInt64 count = 0;
        static SerialPort port;
        static System.IO.StreamWriter file;
        static void Main(string[] args)
        {
            file = new System.IO.StreamWriter(@"C:\Users\li\Desktop\Serial.txt");
            port = new SerialPort("COM6", 9600, Parity.None, 8, StopBits.One);
            port.Handshake = Handshake.None;
            port.Open();

            port.ReadTimeout = 400;
            port.WriteTimeout = 400;
            byte[] output = { 0x7E, 0x64, 0x17, 0x01, 0x45, 0x40, 0xFA, 0x7E };
            port.DataReceived += new SerialDataReceivedEventHandler(SerialPortDataReceived);
            /* Loop, send message, and have event handler handler handle incoming event */
            while (count < UInt64.MaxValue)
            {
                port.Write(output, 0, output.Length);
            }

            return;
        }
        static void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
        {

            SerialPort port = (SerialPort)sender;
            byte[] test = new byte[256];

            try
            {
                string data2 = "";
                port.Read(test, 0, 256);
                for (int i = 0; i < 60; i++)
                {
                    data2 += test[i] + " ";
                }
                string writeOut = count + " - " + DateTime.Now.ToString("h:mm:ss tt") + ": " + data2;
                Console.WriteLine(writeOut);
                file.WriteLine(writeOut);
                count++;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }

        }
    }
}

我在这里创建了一个简单的示例:http://codepen.io/CodinCat/pen/bgoVrw?editors=1010

组件类型(如render (h) { return h('foo', { props: { ...yourData } }) } )和道具都可以是动态的(但您仍然需要声明所有可能的道具字段(例如fooa和{{1} })在你的孩子组件中)

另一种解决方案是JSX。

使用JSX babel插件:https://github.com/vuejs/babel-plugin-transform-vue-jsx

然后你可以使用spread props语法:

b