红枫心声社区

 找回密码
 立即注册

手机动态码快速登录

手机号快速注册登录

搜索
热搜: 活动
查看: 276|回复: 0

Vue3.0 完全教程#3

[复制链接]

33

主题

33

帖子

219

积分

正式会员

Rank: 3Rank: 3

积分
219

活跃会员

发表于 2022-4-30 10:22:52 | 显示全部楼层 |阅读模式
本帖最后由 lovelilt 于 2022-4-30 10:32 编辑

三、Vue3 组件化及组件通信
1、第一个组件(品类组件)
  • 使用 setup 及组件API ,自定义封装 Vue3 组件。
  • defineProps 用于接收父组件传递过来的自定义属性。
  • defineEmits 用于声明父组件传递过来的自定义事件。
  • useStore,配合 computed 实现访问 Vuex中的状态数据。
# 文件名 CnCate.vue <template>
  <div class='cates'>
    <span
      v-for='item in cates'
      v-text='item.label'
      :class='{"on": tab===item.tab}'
      @click='change(item.tab)'
    >
    </span>
  </div>
</template>


<script setup>
  import { defineProps, defineEmits, computed } from 'vue'
  import { useStore } from 'vuex'
  // 接收自定义属性
  const props = defineProps({
    tab: { type: String, default: '' }
  })
  const emit = defineEmits(['update:tab'])
  // 从vuex中访问cates数据
  const store = useStore()
  const cates = computed(()=>store.state.cnode.cates)
  const change = (tab) => {
    emit('update:tab', tab) // 向父组件回传数据
  }
</script>


<style lang="scss" scoped>
.cates {
  padding: 5px 20px;
  background-color: rgb(246, 246, 246);
}
.cates span {
  display: inline-block; height: 24px;
  line-height: 24px; margin-right: 25px;
  color: rgb(128, 189, 1); font-size: 14px;
  padding: 0 10px; cursor: pointer;
}
.cates span.on {
  background-color: rgb(128, 189, 1);
  color: white; border-radius: 3px;
}
</style>

2、第二个组件(分页组件)
  • 使用 toRefs 把 props 变成响应式的。在Vue3中,默认情况下 props是不具备响应式的,即父组件中的数据更新了,在子组件中却是不更新的。
  • 使用 computed 实现动态页码结构的变化。
  • defineProps、defineEmits,分别用于接收父组件传递过来的自定义属性、自定义事件。
# 文件名 CnPage.vue
<template>
  <div class='pages'>
    <span @click='prev'><<</span>
    <span v-if='page>3'>...</span>
    <span
      v-for='i in pages'
      v-text='i'
      :class='{"on":i===page}'
      @click='emit("update:page", i)'
    >
    </span>
    <span>...</span>
    <span @click='emit("update:page", page+1)'>>></span>
  </div>
</template>


<script setup>
  import { defineProps, defineEmits, computed, toRefs } from 'vue'
  let props = defineProps({
    page: { type: Number, default: 1 }
  })
  const { page } = toRefs(props)
  const emit = defineEmits(['update:page'])
  const pages = computed(()=>{
    // 1  1 2 3 4 5 ...
    // 2  1 2 3 4 5 ...
    // 3  1 2 3 4 5 ...
    // 4  ... 2 3 4 5 6 ...
    // n  ... n-2 n-1 n n+1 n+2 ...
    const v = page.value
    return v<=3 ? [1,2,3,4,5] : [v-2,v-1,v,v+1,v+2]
  })
  const prev = () => {
    if (page.value===1) alert('已经是第一页了')
    else emit('update:page', page.value-1)
  }
</script>


<style lang="scss" scoped>
.pages {
  line-height: 50px; text-align: right;
}
.pages>span {
  cursor: pointer; display: inline-block;
  width: 34px; height: 30px; margin: 0;
  line-height: 30px; text-align: center;
  font-size: 12px; border: 1px solid #ccc;
}
.pages>span.on {
  background: rgb(128, 189, 1); color: white;
}
</style>

3、在父级组件中使用 自定义组件
  • v-model:tab='tab' 是 :tab 和 @update:tab 的语法糖简写;
  • v-model:page='page' 是 :page 和 @update:page 的语法糖简写;
  • 使用 watch 监听品类和页面的变化,然后触发调接口获取新数据。
# 文件名 Cnode.vue


<template>
  <div class='app'>
    <!-- <CnCate :tab='tab' @update:tab='tab=$event' /> -->
    <CnCate v-model:tab='tab' />
    <!-- <CnPage :page='page' @update:page='page=$event' /> -->
    <CnPage v-model:page='page' />
  </div>
</template>


<script setup>
  import { ref, watch } from 'vue'
  import CnCate from './components/CnCate.vue'
  import CnPage from './components/CnPage.vue'
  const tab = ref('')
  const page = ref(1)
  const stop = watch([tab, page], ()=>{
    console.log('当品类或页码变化时,调接口')
  })
</script>


您需要登录后才可以回帖 登录 | 立即注册 手机动态码快速登录

本版积分规则

快速回复 返回顶部 返回列表