Массив объектов Prop Decorator StencilJS - PullRequest
0 голосов
/ 04 ноября 2019

Я хочу передать массив объектов, а затем выполнить итерацию по массиву и отобразить каждый объект.

У меня есть следующий мой HTML-файл:

<stencil-component 
   cards = '[{"cardTitle"="placeholder", "copy"="copy1"},{"cardTitle"="placeholder2", "copy"="copy3"}]'>
</stencil-component>

И в моем файле TSXУ меня есть следующее:

@Prop() cards: Array<object> = [];

render(){
    return  (
      {this.cards.map(card) => {

        return (
          <div>
            <h1>{card.cardTitle}</h1>
            <p>{card.copy}</p>
          </div>
        );
      })}    
    )
}

Я не могу даже получить массив для отображения. Я попытался использовать функцию JSON.parse для анализа данных, но это тоже не сработало. Если кто-нибудь может помочь, я был бы очень признателен!

Ответы [ 2 ]

1 голос
/ 06 ноября 2019

Ваша проблема в том, что JSON на самом деле не является JSON (замените = на : ), и далее данные не анализируются автоматически в массиве объектов, когда вы делитесь им черезатрибуты компонента. Я хотел бы использовать универсальную функцию, такую ​​как getDataFromProperty, и передать ее в другой файл, который вы можете использовать во всех ваших веб-компонентах. Но давайте пока все упростим:

@Prop() cards: Array<object> = [];

private getDataFromProperty(toParse):any{
 try(JSON.parse(toParse)){
  return JSON.parse(toParse);
 }catch(e){
  //some different conversations you wanna try e.g.
   console.error('Couldnt JSON parse', e);
   if(toParse.split(',').length > 0) return toParse.split(',');
 }
}

render(){
 if(!this.cards) this.cards = this.getDataFromProperty(this.cards);
    return  (
      {this.cards.map(card) => {

        return (
          <div>
            <h1>{card.cardTitle}</h1>
            <p>{card.copy}</p>
          </div>
        );
      })}    
    )
}

<stencil-component 
   cards = '[{"cardTitle": "placeholder", "copy": "copy1"},{"cardTitle": "placeholder2", "copy": "copy3"}]'>
</stencil-component>

Try and Catch предотвратит некоторые серьезные ошибки и даст вам информацию о том, что произошло, если его не удалось проанализировать. Возможно, вам придется немного подстроить его под свои нужды, но концепция работает. В условии catch вы можете попробовать другие методы для обмена данными.

Во-вторых, я хочу поделиться совершенно другим подходом, который зависит от среды, которую вы используете, но вы можете использовать публичный метод. Чем вы можете напрямую обмениваться данными с веб-компонентом:

@Prop() cards: Array<object> = [];

@Method() setData(data){
  this.cards = data;
}

render(){
  //your render function as it was
}

Внутри вашего HTML

    <stencil-component id="web-component"></stencil-component>
    <script>
     let data = '[{"cardTitle": "placeholder", "copy": "copy1"},{"cardTitle": "placeholder2", "copy": "copy3"}]';

     document.getElementById("web-component").setData(data);
     //just call the setData function from outside works with jquery too
    </script>

Но при таком подходе вы должны обратить внимание на одну небольшую вещь. Возможно, ваша функция визуализации не будет вызвана, чем вы можете сделать это вручную в этой функции, просто используя this.render();, или вы можете использовать декоратор @State перед вашей переменной.

1 голос
/ 05 ноября 2019

Атрибуты HTML могут содержать только строки, поэтому, если вы используете компонент вне Stencil, вам придется передавать все свойства как строки.

В Stencil (и, возможно, в некоторых средах) вы можете передать его следующим образом:

<stencil-component 
   cards={[{"cardTitle":"placeholder", "copy":"copy1"},{"cardTitle":"placeholder2", "copy":"copy3"}]}>
</stencil-component>

Примечание: Ваш JSON неверен, вам нужно заменить = на :.

Если вам нужно использовать компонент в обычном HTML, вам придется либо вручнуюпроанализируйте строку свойства или установите ее, используя javascript.

В документах есть примеры этого :

Установка реквизита вручную

import { Prop } from '@stencil/core';

export class TodoList {
  @Prop() myObject: object;
  @Prop() myArray: Array<string>;
}

HTML

<todo-list></todo-list>
<script>
  const todoListElement = document.querySelector('todo-list');
  todoListElement.myObject = {};
  todoListElement.myArray = [];
</script>

Просмотр изменений реквизита

import { Prop, State, Watch } from '@stencil/core';

export class TodoList {
  @Prop() myObject: string;
  @Prop() myArray: string;
  @State() myInnerObject: object;
  @State() myInnerArray: Array<string>;

  componentWillLoad() {
    this.parseMyObjectProp(this.myObject);
    this.parseMyArrayProp(this.myArray);
  }

  @Watch('myObject')
  parseMyObjectProp(newValue: string) {
    if (newValue) this.myInnerObject = JSON.parse(newValue);
  }

  @Watch('myArray')
  parseMyArrayProp(newValue: string) {
    if (newValue) this.myInnerArray = JSON.parse(newValue);
  }
}

HTML

<todo-list my-object="{}" my-array="[]"></todo-list>
...