javascript SVELTE:动态显示/隐藏单个JSON填充元素

fxnxkyjh  于 2022-12-02  发布在  Java
关注(0)|答案(4)|浏览(258)

问题描述:

  • 按钮1应仅显示/隐藏楼层1的数据。
  • 按钮2应显示/隐藏2楼的数据。
  • 按钮3应显示/隐藏楼层3的数据。

每个按钮都显示/隐藏所有内容。
我可以为每个JavaScript对象重复我的代码,这样就可以工作了--但是我想对引用的任何JSON对象的重复进行抽象。
我尝试了不同的方法,但放弃了,决定这样问。看到回复会帮助我“思考SVELTE”
https://svelte.dev/repl/6e498fa577674323b4a602b4b4b3acf2?version=3.53.1

<div class="parent-container">
  {#each rooms as room}
  <button on:click={showHide}>Floor number {room.floor} </button>

  {#if showState}
     <div class={showState}>
      <h2>{room.floor}</h2>
       {#each room.rooms as singleRoom}
    <div>
      <h2>{singleRoom.number}</h2>
      
    </div>

    {/each}
    </div>
    {/if}

    {/each}
</div>

<script>   

let showState = "hide";

function showHide(){
  showState = (showState ==="hide") ? "show" : "hide";
}

let rooms =[
  {
    floor:1,
    rooms:[{number:101},{number:102},{number:103}]
  },
  {
    floor:2,
    rooms:[{number:201},{number:202},{number:203}]
  },

    {
    floor:3,
    rooms:[{number:301},{number:302},{number:303}]
  },

]

</script>

<style>
  .hide{
    display: none;
  }
</style>
9q78igpj

9q78igpj1#

You currently only have one state for multiple objects. There are multiple ways of approaching this:

  • Extract the content of the #each into a separate component, that way each object will have its own separate state
  • Store the visibility alongside the data (if that is not an issue)
  • Store the visibility in a separate object or array

E.g. storing the state in a separate array:

<div class="parent-container">
  {#each rooms as room, i}
    <button on:click={() => showHide(i)}>Floor number {room.floor} </button>

    {#if visibility[i]}
      <div>
        <h2>{room.floor}</h2>
        {#each room.rooms as singleRoom}
          <div><h2>{singleRoom.number}</h2></div>
        {/each}
      </div>
    {/if}
  {/each}
</div>

<script>
  let rooms = [
    { floor: 1, rooms: [{number:101},{number:102},{number:103}] },
    { floor: 2, rooms: [{number:201},{number:202},{number:203}] },
    { floor: 3, rooms: [{number:301},{number:302},{number:303}] },
  ];

  let visibility = new Array(rooms.length).fill(false);

  function showHide(index) {
    visibility[index] = !visibility[index];
  }
</script>

Here the index provided by the #each is used to access the visiblity array.

piah890a

piah890a2#

You said that you want to "think Svelte", so I think the most idiomatic option would be to extract the logic for each floor into a new Floor component and let each instance manages its own state.
Honestly, I'm surprised no one else suggested this. Using this solution, you can have as many rooms as you want, and helps separate your code. You can do it like this:
Run it on the Svelte REPL

App.svelte

<script>
    import Floor from './Floor.svelte';
    
    let rooms =[
      {
        floor:1,
        rooms:[{number:101},{number:102},{number:103}]
      },
      {
        floor:2,
        rooms:[{number:201},{number:202},{number:203}]
      },
    
        {
        floor:3,
        rooms:[{number:301},{number:302},{number:303}]
      },
    ];
</script>

<div class="parent-container">
  {#each rooms as room}
        <Floor room={room}/>
  {/each}
</div>

Floor.svelte

<script>
    export let room;
    
    let showState = false;
    function showHide() {
        showState = !showState;
    }
</script>

<style>
    .hide{
        display: none;
    }
</style>

<button on:click={showHide}>Floor number {room.floor} </button>

{#if showState}
    <div class:hide={!showState}>
        <h2>{room.floor}</h2>
        {#each room.rooms as singleRoom}
            <div>
                <h2>{singleRoom.number}</h2>
            </div>
        {/each}
    </div>
{/if}

I also changed showState into a boolean. This makes it a bit easier to understand and follow along. Also, as @Corrl pointed out, it is better to use the class: directive instead of an if-statement.

ryevplcw

ryevplcw3#

我喜欢@ MichaelM的solution将地板逻辑和样式移动到它自己的地板组件中。这种组件分离的做法将使编辑或重用代码更容易。
然而,我也相信代码越少,编写代码就越容易。所以我建议下面这个稍微简单一些的解决方案(或者试试REPL here),它将可视性作为一个元素添加到楼层数据中,并允许数据驱动逻辑,而不是相反。如果你想了解更多,这个解决方案还利用了Svelte的内联处理程序功能。希望这对你有所帮助!

<div class="parent-container">
  {#each floors as floor}
        <button on:click={() => floor.visibility = floor.visibility * -1}>
            Floor number {floor.floor}
        </button>
        {#if floor.visibility === 1}
            <!--<div class=yourstyleclasshere>-->
                <h2>Floor: {floor.floor}</h2>
                    {#each floor.rooms as singleRoom}
                        <div>
                            <h2>{singleRoom.number}</h2>
                        </div>
                    {/each}
            <!--</div>-->
        {/if}
  {/each}
</div>

<script>   
let floors = [
  {
    floor:1,
    rooms:[{number:101},{number:102},{number:103}],
    visibility: -1
  },
  {
    floor:2,
    rooms:[{number:201},{number:202},{number:203}],
    visibility: -1
  },

    {
    floor:3,
    rooms:[{number:301},{number:302},{number:303}],
    visibility: -1
  }
]
</script>
aiqt4smr

aiqt4smr4#

需要使用数组为每个房间设置showState,并使用属性存储楼层号,并在事件中使用this.getAttribute('attr-data-floor')获取楼层号:

<div class="parent-container">
  {#each rooms as room}
  <button on:click={showHide} attr-data-floor={room.floor}>Floor number {room.floor} </button>

  {#if showState[room.floor] }
     <div class={showState[room.floor]}>
      <h2>{room.floor}</h2>
       {#each room.rooms as singleRoom}
    <div>
      <h2>{singleRoom.number}</h2>
      
    </div>

    {/each}
    </div>
    {/if}

    {/each}
</div>

<script>   

let showState ={1:"hide", 2:"hide",3:"hide"} ; //one mor because 0

function showHide(){
    let num = this.getAttribute('attr-data-floor') ;
  showState[num] = (showState[num] ==="hide") ? "show" : "hide";
}

let rooms =[
  {
    floor:1,
    rooms:[{number:101},{number:102},{number:103}]
  },
  {
    floor:2,
    rooms:[{number:201},{number:202},{number:203}]
  },

    {
    floor:3,
    rooms:[{number:301},{number:302},{number:303}]
  },

]

</script>

<style>
  .hide{
    display: none;
  }
</style>

相关问题