You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue:点击按钮动态生成.container实例的最优实现方法问询

Vue: Dynamic, Stateful Div Creation (Better Than appendChild)

Hey there! Great start with your toggle function—let's build on that to create dynamic, repeatable .container instances the Vue way. Forget manual DOM manipulation like appendChild; Vue's data-driven approach is cleaner, more maintainable, and keeps your state in sync automatically.

The Core Idea

Instead of tinkering with the DOM directly, we'll use an array in our parent component to track how many dynamic containers we need. Each container will be its own reusable child component, so every instance gets independent collapse/expand state (no cross-instance interference!).

Step 1: Split into Reusable Components

First, let's extract the collapsible container logic into its own component. This ensures each new instance manages its own state separately:

Vue.component('CollapsibleContainer', {
  template: `
    <div class="container">
      <div class="createdDiv" v-if="displayDiv">
        <h2>I am dynamic!</h2>
        <button class="minimize" @click="toggle">Make me small</button>
      </div>
      <div class="createdDivMinimized" v-else>
        <p>I am a small version of the created div!</p>
        <button class="maximize" @click="toggle">Expand me</button>
      </div>
    </div>
  `,
  data() {
    return {
      displayDiv: true // Start expanded by default—adjust this if needed
    };
  },
  methods: {
    toggle() {
      this.displayDiv = !this.displayDiv;
    }
  }
});

Step 2: Parent Component with Dynamic Instance Tracking

Our parent component will manage a list of containers. Every time the "Create" button is clicked, we'll add a new entry to our array. Vue's v-for will automatically render a new CollapsibleContainer for each entry:

Vue.component('DynamicDivs', {
  template: `
    <div>
      <div class="headerDiv">
        <button class="addDiv" type="button" @click="addContainer">Create</button>
      </div>
      <!-- Render one container for each item in our array -->
      <CollapsibleContainer v-for="(container, index) in containers" :key="index" />
    </div>
  `,
  data() {
    return {
      containers: [] // Empty array means only the button shows initially
    };
  },
  methods: {
    addContainer() {
      // Push any value—we just need to increment the array length to trigger a new render
      this.containers.push({});
    }
  }
});

Step 3: Your CSS (Polished for Better UX)

I kept your original styles and added a few tweaks for layout:

.headerDiv {
  height: 100px;
  width: 400px;
  background-color: blue;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
}
.createdDiv {
  height: 300px;
  width: 400px;
  background-color: black;
  color: white;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.createdDivMinimized {
  height: 300px;
  width: 400px;
  background-color: red;
  color: white;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.addDiv, .minimize, .maximize {
  padding: 8px 16px;
  cursor: pointer;
  border: none;
  border-radius: 4px;
}

Step 4: Final HTML Setup

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="parent">
  <DynamicDivs></DynamicDivs>
</div>

<script>
new Vue({
  el: '#parent'
});
</script>

Why This Is Better Than appendChild

  • Data-Driven: Vue handles all DOM updates for you—no manual DOM manipulation means fewer bugs and cleaner code.
  • Isolated State: Each collapsible container has its own displayDiv state, so toggling one doesn't affect others.
  • Scalable: Want to add delete buttons, or pass unique data to each container? Just update the array and component props.
  • Reusable: The CollapsibleContainer component can be dropped into any other part of your app.

内容的提问来源于stack exchange,提问作者josefdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:02:56