首頁  >  問答  >  主體

Vue 2中實作父子元件無限循環的方法:使用插槽

<p>我需要從父元件呼叫子元件的一個方法。然而,我在子組件中做的一些事情似乎導致了一個無限循環。我嘗試過查看其他問題,雖然它們似乎正在解決類似的問題,但我無法將它們的確切模式應用到我面臨的問題上,它似乎是不同的。我只是不確定我在看什麼。 </p> <p>我有兩個元件,一個叫做ToggleButtons,另一個被簡化為一個按鈕。這是ToggleButtons:</p> <pre class="brush:php;toolbar:false;"><template> <div role="list"> <div role="listitem"> <slot name="left" :is-selected="leftSelected" :toggleLeft="toggle('left')" /> </div> <div role="listitem"> <slot name="right" :is-selected="rightSelected" :toggleRight="toggle('right')"/> </div> </div> </範本> <腳本> 導出預設值{ 道具: { 左選擇初始:{ 類型:布林值, 預設值:真, } }, 數據() { 返回 { 左選擇:真, 右選擇:假, } }, 之前安裝(){ this.leftSelected = this.leftSelectedInitially; this.rightSelected = !this.leftSelectedInitially; }, 方法: { 切換(覆蓋){ this.leftSelected = override == '左'; this.rightSelected = override == '右'; } } } </劇本></pre> <p>這就是它與按鈕的實現:</p>

    <模板 v 槽:左=”{
        已選定,
    }>>
        <按鈕
            類別=“按鈕”
            :class="{ secondary: !isSelected }"
            :aria-pressed="isSelected"
            :togglable=“真”
            v-text="'左'"
            @click=“切換('左')”
        >>
    </範本>
    <模板 v-slot:right="{
        已選定,
    }>>
        <按鈕
            類別=“按鈕”
            :class="{ secondary: !isSelected }"
            :aria-pressed="isSelected"
            :togglable=“真”
            v-text="'右'";
            @click=“切換('右')”
        >>
    </範本>
</切換按鈕></pre>
<p>其中切換方法為:</p>
<pre class="brush:php;toolbar:false;">切換(方向){
    this.$refs.tb.toggle(方向);
},</pre>
<p>正如你可能已經從程式碼中看到的殘留物,我之前嘗試過各種模式,包括透過 v-slot 提交切換方法。所有這些都導致​​了相同的「你創建了一個無限循環」的訊息。</p>
<p>我想知道是否因為該方法在嘗試渲染時調用了切換。我不確定這是否會導致無限循環。我在這裡的主要問題是我不明白這個循環是從哪裡來的。我目前的主要目標是理解生長什麼問題,這樣如果再次發生,我就能看到它,即使修復方法只是找到一個更簡單的方法。</p>
P粉128563140P粉128563140412 天前464

全部回覆(1)我來回復

  • P粉727531237

    P粉7275312372023-09-04 12:48:32

    以下對toggle函數的綁定對我來說沒有任何意義:

    :toggleLeft="toggle('left')"
    :toggleRight="toggle('right')

    由於函數不會傳回任何值,所以這是錯誤的。

    這兩個綁定會導致函數無限呼叫toggle('left')toggle('right')

    只需在toggle函數中新增console.log(direction)以查看發生了什麼。

    如果您想獲得關於正確解決方案的建議,請描述您想要實現的目標。

    Vue.component('toggle-buttons',{
      props: {
        leftSelectedInitially: {
            type: Boolean,
            default: true,
        }
      },
      data() {
          return {
              leftSelected: true,
              rightSelected: false,
          }
      },
      beforeMount() {
          //this.leftSelected = this.leftSelectedInitially;
          //this.rightSelected = !this.leftSelectedInitially;
      },
      methods: {
          toggle(override) {
              console.log(`override: ${override}`)
              this.leftSelected = override == 'left';
              this.rightSelected = override == 'right';
          }
      },
      template: `
    <div role="list">
      <div role="listitem">
          <slot name="left" :is-selected="leftSelected" :toggleLeft="toggle('left')" />
      </div>
      <div role="listitem">
          <slot name="right" :is-selected="rightSelected" :toggleRight="toggle('right')" />
      </div>
    </div>
    `
    });
    
    new Vue({
      el:'#app',
      methods: {
      toggle(direction) {
        console.log(`direction: ${direction}`)
        this.$refs.tb.toggle(direction);
        }
      }
    })
    #app { line-height: 2; }
    [v-cloak] { display: none; }
    <div id="app">
    <toggle-buttons ref="tb">
        <template v-slot:left="{ isSelected }">
            <button
                class="button"
                :class="{ secondary: !isSelected }"
                :aria-pressed="isSelected"
                :togglable="true"
                v-text="'left'"
                @click="toggle('left')"
            />
        </template>
        <template v-slot:right="{ isSelected }">
            <button
                class="button"
                :class="{ secondary: !isSelected }"
                :aria-pressed="isSelected"
                :togglable="true"
                v-text="'right'"
                @click="toggle('right')"
            />
        </template>
    </toggle-buttons>
    </div>
    <script src="https://unpkg.com/vue@2/dist/vue.min.js"></script>

    回覆
    0
  • 取消回覆