<script src="https://unpkg.com/vue@next"></script>
<div id="app">
  <p>{{text}}</p>
  <input type="text" v-model="text"/>
  <!-- v-if 會直接拔除、塞入 DOM-->
  <p v-if="message.show">{{message.name}}</p>
  <p>Number: {{number}}</p>
  <p>Multiple * 5 : {{multipleNumber}}</p>
  <p>Object Index: {{indexInObject.index}}</p>
  <button @click="add">Add</button>
  <button @click="minus">Minus</button>
  <button @click="addToReadOnly">AddToReadOnly</button>
  <button @click="changeMessageStatus">Show / Hide Message</button>
  <br/>
  <br/>
  <div class="box__wrapper">
    <a href="#" @click="displayCountryCode">Click to open / close</a>
    <ul :class="['box',{open:isOpen}]">
      <!-- v-show 用 css 的方法來控制開關-->
      <!-- v-bind:key 可以避免更動時都重新渲染,避免使用 array index 當 key,以免渲染錯誤-->
      <!-- v-if 和 v-for 是不能同時使用的,v-if 的優先權高於 v-for-->
      <!-- 請先用 js 篩選完資料後,再用 v-for -->
      <li
        v-for="(country,index) in countryCodes"
        :key="country.code"
        v-show="country.show"
        :class="[country.class,{open:isOpen}]"
      >
        {{index+1}}. {{country.name}} | {{country.code}}
      </li>
    </ul>
  </div>
</div>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.box{
    padding:12px;
    background-color: rgb(218, 214, 214);
    transition: height 0.4s;
    height:0px
}
.box.open{
    height:120px;
}
.box > li{
    display: none;
    justify-content: center;
    align-items: center;
    transition: height 0.4s;
}
.box > li.open{
    display: flex;
}
.red{
    color:red;
}
.blue{
    color:blue
}
const { ref, reactive, readonly, computed } = Vue;
const App = {
  setup () {
    // 用 Vue.ref() 作綁定, 綁定後會有一個屬性為 value
    // 修改其 value 後,畫面值會變動
    const isOpen = ref(true)
    const text = ref('Hello Vue!')
    const number = ref(0)
    const copyNumber = readonly(number)
    const countryCodes = ref([
      { name: 'Taiwan', code: '886', show: true, class: 'red' },
      { name: 'Japan', code: '81', show: true, class: 'red' },
      { name: 'United States', code: '1', show: false, class: 'blue' },
      { name: 'United Kingdom', code: '44', show: true, class: 'blue' },
      { name: 'Singapore', code: '65', show: true, class: 'blue' }
    ])

    // reactive 僅接受 [],{},可以進行深層檢查,不需要用 .value 就可以取得值
    const message = reactive({ name: 'Steve Jobs', show: true })
    const indexInObject = reactive({ index: 0 })

    // 若你有方法要給 template 的模板作操作,那一定要在 setup 中 return
    const add = () => {
      number.value += 1
      indexInObject.index += 2
    }
    const minus = () => {
      number.value -= 1
      indexInObject.index -= 2
    }

    const addToReadOnly = () => {
      copyNumber.value += 1
    }

    const changeMessageStatus = () => {
      message.show ? message.show = false : message.show = true
    }

    const displayCountryCode = () => {
      isOpen.value = !isOpen.value
    }

    // 經由 computed 計算後,若要取值都得加上 .value
    const multipleNumber = computed(() => {
      return number.value * 5
    })

    setTimeout(() => {
      text.value = 'Hello World!'
    }, 1000)

    return { text, message, number, add, minus, indexInObject, addToReadOnly, countryCodes, changeMessageStatus, isOpen, displayCountryCode, multipleNumber }
  }
}

Vue.createApp(App).mount("#app");
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.cjs.js