Vue3 setup语法糖使用以及对比不用语法糖写法(#仅供学习)

学习内容:Vue3 setup语法糖
1、实例:轮播图效果

请添加图片描述
2、实现过程(轮播图(子组件)+左右按钮(父页面))
准备页面(App.vue:父页面+Carousel.vue:子组件)
在这里插入图片描述
3、Carousel.vue:子组件
在这里插入图片描述
使用setup语法糖写法
在这里插入图片描述
vue3的编译宏:
在这里插入图片描述
不使用语法糖写法
在这里插入图片描述
Carousel.vue代码,提供setup语法糖写法

<template>
    <div v-show="imgs.length" class="carousel">
        <div class="imgs" :style="{transform: `translateX(-${index}00%)`}">
            <!-- :style="{transform: `translateX(-${index}00%)`,}:
                :style:样式绑定,当表达式的值改变时,元素的样式也会相应地更新
                translateX(-${index}00%):X轴(水平方向)上移动元素
                -${index}00%:模版字符串,元素会向左移动其自身宽度的 index00% ,例如index:1,向左移动自身100%
                表示水平移动的位置 -->
            <!-- 存放图片 -->
            <img v-for="(item, i) in imgs" :key="i" :src="item" alt="" />
        </div>
        <!-- 四个半透明白色点 -->
        <!-- :class="{ active: i === index }":表示高亮哪一个点 -->
        <div class="indicators">
            <span v-for="(item, i) in imgs" :key="i" :class="{ active: i === index }" @click="switchTo(i)"></span>
        </div>
    </div>
</template>

<script setup>
import { ref } from 'vue';
// defineProps、defineEmits:编译器宏
const props = defineProps({
    imgs: {
        type: Array,
        default: () => [],
    },
})
const emit = defineEmits(['change'])
defineExpose({
    switchTo
})
const index = ref(0);
function switchTo(i) {
    if (i < 0) {
        i = 0
    } else if (i > props.imgs.length - 1) {
        i = props.imgs.length - 1
    }
    if (i === index.value) {
        return;
    }
    index.value = i
    emit('change', i);
}
</script>

<style scoped>
.carousel {
    width: 300px;
    height: 300px;
    overflow: hidden;
    position: relative;
}

.imgs {
    width: 100%;
    height: 100%;
    display: flex;
    transition: 0.3s;
}

.imgs img {
    width: 100%;
    height: 100%;
}

.indicators {
    position: absolute;
    left: 50%;
    bottom: 20px;
    transform: translateX(-50%);
    display: flex;
    column-gap: 7px;
}

.indicators span {
    width: 10px;
    height: 10px;
    background: #aaa;
    border-radius: 50%;
    cursor: pointer;
}

.indicators span.active {
    background: #fff;
}
</style>

App.vue父页面代码:
在这里插入图片描述
使用语法糖
在这里插入图片描述
不使用语法糖:
在这里插入图片描述

父页面代码:

<!-- <template>
  <div id="app">
    <CheckEditor v-model="checked" v-model:title.trim="title" />
    <p>選中狀態{{ checked }}</p>
    <p>商品名稱{{ title }}</p>
      </div>

  <div class="container">
    <div>
      <strong>编辑</strong>
      <div class="list">
        <CheckEditor v-for="item in products" :key="item.id" v-model="item.sell" v-model:title="item.title">
        </CheckEditor>
      </div>
    </div>
    <div class="list">
      <strong>销售中:</strong>
      <div>
        <template v-for="(item, index) in sells" :key="item.id">
          <span>{{ index + 1 }}</span>
          <strong>{{ item.title }}</strong>
        </template>
      </div>
    </div>
  </div>

  <div>
    <div v-if="isAccount">
      <label>账号:</label>
      <input type="text" />
    </div>
    <div v-else>
      <label>手机登录:</label>
      <input type="text" />
    </div>
    <button @click="isAccount = !isAccount">切换登录方式</button>
  </div>


</template>
<script>
import CheckEditor from './components/CheckEditor.vue';
import { ref, computed } from "vue";

const defaultSells = [
  {
    id: 1, sell: true, title: "iphone1"
  },
  {
    id: 2, sell: false, title: "iphone2"
  },
  {
    id: 3, sell: true, title: "iphone3"
  },
  {
    id: 4, sell: true, title: "iphone4"
  }
]

export default {
  components: {
    CheckEditor,
  },
  setup() {
    const productsRef = ref(defaultSells);

    const sellsRef = computed(() => productsRef.value.filter((it) => it.sell))

    const isAccount =ref(false)
    return {
      products: productsRef,
      sells: sellsRef,
      isAccount: isAccount
    }
  },

};
</script>
<style scoped>
.container {
  margin-top: 50px;
  width: 880px;
  margin: 50px auto;
}

.list {
  display: flex;
  margin: 1em 0;
  align-items: center;
}

strong {
  margin-right: 1em;
}
</style> -->

<!-- <template>
  <div id="nav">
    <router-link to="/">Home</router-link>
    |
    <span v-if="loading">loading....</span>
    <template v-else-if="user">
      <span>用户名</span>
      <a class="ml-5" href="" @click.prevent="handleLoginOut">退出</a>
    </template>
    <router-link v-else to="/login">Login</router-link>
  </div>
  <router-view />
</template>

<script>
import {useStore} from "vuex";
import {computed} from "vue";
import { useRoute } from "vue-router";
export default {
setup(){
  const store = useStore();
  const router = useRoute()
  const handleLoginOut = async ()=>{
    await store.dispatch("loginUser/loginOut")
    router.push("/login")
  }
  return {
    loading:computed(()=>store.state.loginUser.loading),
    user:computed(()=>store.state.loginUser.user),
    handleLoginOut

  }
}
}
</script>

<style scoped>
 body {
   font-family: Avenir, Helvetica, Arial, sans-serif;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
   text-align: center;
   color: #2c3e50;
 }

 #nav {
   padding: 30px;
 }

 #nav a {
   font-weight: bold;
   color: #2c3e50;
 }

 #nav a.router-link-exact-active {
   color: #42b983;
 }
</style> -->


<template>
  <div class="container">
    <!-- 引入组件 change 是改变父组件的页面dom-->
    <Carousel ref="compRef" :imgs="datas" @change="handleChange"></Carousel>
    <div class="current">
      <!-- :disabled="currentIndex === 0":当前图片为第一张时,左按钮禁用 -->
      <button class="btn" @click="change(currentIndex - 1)" :disabled="currentIndex === 0">
        左
      </button>
      {{ currentIndex }}
      <!-- :disabled="currentIndex === datas.length - 1":当前图片为最后一张时,右按钮禁用 -->
      <button class="btn" @click="change(currentIndex + 1)" :disabled="currentIndex === datas.length - 1">
        右
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import Carousel from './components/Carousel.vue';
const currentIndex = ref(0);
const datas = [//图片数据
  new URL(`./assets/bule.png`, import.meta.url),
  new URL(`./assets/airplane.png`, import.meta.url),
  new URL(`./assets/red.png`, import.meta.url),
  new URL(`./assets/sky.png`, import.meta.url),
];
const compRef = ref(null);
function handleChange(newIndex) {//改变 {{ currentIndex }}的值
  currentIndex.value = newIndex
}
function change(i) {//点击按钮改变数据后,使用ref触发子组件方法
  if (compRef.value) {
    compRef.value.switchTo(i)
  }
}
</script>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  border: 1px solid slateblue;
}

.current {
  display: flex;
  column-gap: 10px;
  margin-top: 30px;
  align-items: center;
}

.btn {
  border: none;
  outline: none;
  background: #409eff;
  color: #fff;
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  text-align: center;
  transition: 0.1s;
  font-weight: 500;
  user-select: none;
  padding: 12px 20px;
  font-size: 14px;
  border-radius: 4px;
}

.btn:hover {
  background: #66b1ff;
}

.btn:active {
  background: #3a8ee6;
}

.btn:disabled {
  background: #66b1ff80;
  cursor: not-allowed;
}
</style>

使用语法糖的switchTo方法在这里插入图片描述

本次分享vue3使用语法糖的使用以及不使用语法糖使用的写法区别
1、写法上不在使用export default{}以及不需要注册组件
2、使用语法糖暴露的方法很干净,避免数据污染
3、简化了开发

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值