如何使用ES6类在Vue.js中实现派生渲染实现

马塞尔

对于此查询的长度,我们事先表示歉意。

在React中,我可以在任何返回JSX.Element的标准ES6类上使用render函数。这很出色,因为它允许我派生ES6类,其中每个派生类都实现自己的JSX呈现实现-请参见下面的(ts)示例:

export class Colour {
  public name: string = "";

  constructor(name) {
    this.name = name;
  }

  public render(): JSX.Element {
    return <span>Error, no colour specified</span>;
  }
}

export class Red extends Colour {
  constructor() {
    super("red");
  }
  public render(): JSX.Element {
    return <div style={{ color: this.name }}>Hi, I am {this.name}!</div>;
  }
}

export class Blue extends Colour {
  constructor() {
    super("blue");
  }
  public render(): JSX.Element {
    return <h2 style={{ color: this.name }}>Hi, I am {this.name}!</h2>;
  }
}  

然后,在React组件中,我可以创建一个可以轻松呈现的Color对象列表,如下所示:

function App() {
  const list = [];
  list.push(new Red());
  list.push(new Blue());
  list.push(new Red());

  const listItems = list.map(item => <li key={item}>{item.render()}</li>);

  return (
    <div className="App">
      <h1>React derived rendering </h1>
      <ul>{listItems}</ul>
    </div>
  );
} 

结果是这样的:

在此处输入图片说明

一切都很好...

现在我的问题是:在Vue.js中,有什么方法可以轻松地做到这一点吗?请注意-对我而言,在代码中创建许多派生实例并将其添加到要呈现的列表中很重要!

现在,我能做的最接近的工作是创建一个虚拟Vue组件,当它渲染时,我实际上调用派生的实现来交出渲染句柄“ h”。

Vue.component("fusion-toolbar", {
  props: ["items"],
  template: `
            <div>
                <div v-for="item in items" 
                    v-bind:key="item.code" >
                        <f-dummy v-bind:item='item'></f-dummy>
                </div>
            </div>
        `
});

Vue.component("f-dummy", {
  props: ["item"],
  render(h) {
    return this.item.render(h);
  }
});

export class Colour {
    public colour: string = "";

    constructor(colour: string) {
        this.colour = colour;
    }

    render(h: any) {
        return h("h1", "Hello, I am " + this.colour);
    }

}

export class Red extends Colour {
    constructor() {
        super("red");
    }

    render(h: any) {
        return h("h2", "Hello, I am " + this.colour);
    }
}

export class Blue extends Colour {
    private _isDisabled = true;

    constructor(disabled: boolean) {
        super("blue");
        this._isDisabled = disabled;
    }

    render(h: any) {
        return h('div',
            [
                h('h4', {
                    class: ['example-class', { 'conditional-class': this._isDisabled }],
                    style: { backgroundColor: this.colour }
                }, "Hello, I am " + this.colour)
            ]
        )
    }
}

然后在我的父列表组件中,我有:

<template>
  <div id="app"><fusion-toolbar v-bind:items="myitems"> </fusion-toolbar></div>
</template>

<script>
import { Red, Blue } from "./Colour";

export default {
  name: "App",
  data: function() {
    return {
      myitems: []
    };
  },
  mounted() {
    this.myitems.push(new Red());
    this.myitems.push(new Blue(false));
    this.myitems.push(new Blue(true));
  }
};
</script>

这是最好的方法吗?欢迎任何反馈...

马塞尔

经过一段时间的思考,我不得不得出结论,我的烦恼来自必须引入“ f-dummy”中间组件,以便能够捕获Vue的render函数,然后将其传递给pojo。

我现在更改的是,我使用较低级别的“ render(createElement)”(或“ h”)句柄渲染列表本身,然后可以将其传递给子级,而不必求助于中间组件

这是新代码,首先我定义ES6类(请注意,颜色,橙色,蓝色只是示例):

export class Colour {
    public colour: string = "";

    constructor(colour: string) {
        this.colour = colour;
    }

    render(h: any) {
        return h("h1", "Error - please provide your own implementation!");
    }
}

export class Orange extends Colour {
    constructor() {
        super("orange");
    }

    public getStyle() {
        return {
            class: ['example-class'],
            style: { backgroundColor: this.colour, border: '3px solid red' }
        }
    }

    render(h: any) {
        return h('h4', this.getStyle(), "This is my colour: " + this.colour)
    }
}

export class Blue extends Colour {
    private _isDisabled = true;

    constructor(disabled: boolean) {
        super("lightblue");
        this._isDisabled = disabled;
    }

    render(h: any) {
        return h('div',
            [
                h('h4', {
                    class: ['example-class', { 'is-disabled': this._isDisabled }],
                    style: { backgroundColor: this.colour }
                }, "Hello, I am " + this.colour)
            ]
        )
    }
}

要渲染列表,我现在这样做:

Vue.component("fusion-toolbar", {
  props: ["items"],
  render(h: any) {
    return h('div', this.items.map(function (item: any) {
      return item.render(h);
    }))
  }
});

现在,我可以简单地将Orange或Blue'pojo'实例添加到列表中,它们将正确呈现。请参阅以下App.vue的内容:

<template>
  <div id="app">
    <fusion-toolbar v-bind:items="myitems"> </fusion-toolbar>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import { Colour, Orange, Blue } from "./components/DropDownItem";

export default Vue.extend({
  name: "app",
  data: function() {
    return {
      myitems: [] as Colour[]
    }
  },
  mounted() {
    this.myitems.push(new Orange());
    this.myitems.push(new Blue(false));
    this.myitems.push(new Blue(true));
  }
});
</script>

<style lang="scss">
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  text-align: center;
}

.example-class {
  width: 250px;
  padding: 3px;
}

.is-disabled {
  color: gray;
}

</style>

样本如下所示:

在此处输入图片说明

很整齐。我意识到我可以使用Babel插件来使用JSX来代替Vue的较低层渲染,但是我很享受它给我带来的力量!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章