Vue3 script setup 语法糖(升级版)

简介: vue3

序:

​ 使用了vue3后发现变量每次都必须return,不免很麻烦,所以在vue3.2添加了script setup 语法糖,本次修改主要从以下5个方面做了修改:

1.SSR:服务端渲染优化。@vue/server-renderer包加了一个ES模块创建, 与Node.js解耦,使在非Node环境用@vue/serve-render做服务端渲染成为可能, 比如(Workers、Service Workers)

2.New SFC Features:新的单文件组件特性

3.Web Components:自定义 web 组件。这个我们平时很少用到,但是应该知道

4.Effect Scope API: effect 作用域, 用来直接控制响应式副作用的释放时间(computed 和 watchers)。 这是底层库的更新,开发不用关心,但是应该知道

5.Performance Improvements:性能提升。这是内部的提升,跟开发无关

一、变量、方法不需要 return 出来

<template>
  <div class="home">
    显示的值{{flag }}
    <button @click="changeHander">改变值</button>
  </div>
</template>
<!-- 只需要在script上添加setup -->
<script setup="props, { emit }" lang="ts">
    import { ref } from 'vue';

    <!-- flag变量不需要在 return出去了 -->
    let flag=ref("开端-第一次循环")

    <!-- 函数也可以直接引用,不用在return中返回 -->
    let changeHander=():void=>{
        flag.value='开端-第二次循环'
    }

</script>

官方中文文档

二、组件不需要在注册

在 script setup 中,引入的组件可以直接使用,无需再通过components进行注册,并且无法指定当前组件的名字,它会自动以文件名为主,也就是不用再写name属性了

<!-- 这个是组件 -->
<template>
    <div>
        <h2> 你好-我是肖鹤云</h2>
    </div>
</template>


<!-- 使用的页面 -->
<template>
  <div class="home">
    <test-com></test-com>
  </div>
</template>
<script lang="ts" setup>
// 组件命名采用的是大驼峰,引入后不需要在注册,是不是爽歪歪呀!
//在使用的使用直接是小写和横杠的方式连接 test-com
import TestCom from "../components/TestCom.vue"
</script>

三、新增 defineProps、defineEmits、defineExpose

1、父传子

<!-- 父组件传递参数 -->
<template>
  <div class="home">
    <test-com :info="msg" time="42分钟"></test-com>
  </div>
</template>
<script lang="ts" setup>
// 组件命名采用的是大驼峰,引入后不需要在注册,是不是爽歪歪呀!
import TestCom from "../components/TestCom.vue"
let msg='公交车-第一次循环'
</script>


<!-- 子组件接受参数 -->
<template>
    <div>
        <h2> 你好-我是肖鹤云</h2>
        <p>信息:{{ info}}</p>
        <p>{{ time }}</p>
    </div>
</template>
<script lang="ts" setup>
import {defineProps} from 'vue'
defineProps({
    info:{
        type:String,
        default:'----'
    },
    time:{
        type:String,
        default:'0分钟'
    },
})
</script>

2、子传父

defineEmits

<!-- 子组件使用 -->
<template>
    <div>
        <h2> 你好-我是肖鹤云</h2>
        <button @click="hander1Click">新增</button>
        <button @click="hander2Click">删除</button>
    </div>
</template>

<script lang="ts" setup>
 import {defineEmits} from 'vue'
//  使用defineEmits创建名称,接受一个数组
let $myemit=defineEmits(['myAdd','myDel'])
let hander1Click=():void=>{
    $myemit('myAdd','新增的数据')
}

let hander2Click=():void=>{
    $myemit('myDel','删除的数据')
}
</script>


<!-- 父组件 -->
<template>
  <div class="home">
    <test-com @myAdd="myAddHander" @myDel='myDelHander'></test-com>
  </div>
</template>
<script lang="ts" setup>
// 组件命名采用的是大驼峰,引入后不需要在注册,是不是爽歪歪呀!
//在使用的使用直接是小写和横杠的方式连接 test-com
import TestCom from "../components/TestCom.vue"
let myAddHander=(mess):void=>{
  console.log('新增==>',mess);
}

let myDelHander=(mess):void=>{
  console.log('删除==>', mess);
}
</script>

defineExpose

<!-- 子组件 -->
<template>
    <div class="child"></div>
</template>

<script setup lang="ts">
import { ref, reactive } from "vue";
function doSth() {
    console.log(333);
}
defineExpose({ doSth });
</script>

<style lang="scss" scoped>
</style>


<!-- 父组件 -->
<template>
<div class="father" @click="doSth1">222</div>
    <Child ref="childRef"></Child>
</template>

<script setup lang="ts">
import { ref, reactive } from "vue";
import Child from "./Child.vue";
const childRef = ref();
function doSth1() {
    childRef.value.doSth();
}
</script>

<style lang="scss" scoped>
</style>

3、小结

// 第一种不带默认值props
const props = defineProps<{
  foo: string
  bar?: number
}>()
// 第二种带默认值props

export interface ChildProps {
  foo: string
  bar?: number
}

const props = withDefaults(defineProps<ChildProps>(), {
   foo: "1qsd"
  bar?: 3
})

// 第一种获取事件
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()

// 第二种获取事件
 
const emit = defineEmits(["dosth"])

四、新增指令 v-memo

v-memod会记住一个模板的子树,元素和组件上都可以使用。 该指令接收一个固定长度的数组作为依赖值进行[记忆比对]。 如果数组中的每个值都和上次渲染的时候相同,则整个子树的更新会被跳过。 即使是虚拟 DOM 的 VNode 创建也将被跳过,因为子树的记忆副本可以被重用。 因此渲染的速度会非常的快。

注意:正确地声明记忆数组是很重要。

<li v-for="item in listArr"  :key="item.id"  v-memo="['valueA','valueB']">
    {{ item.name   }}
</li>

作用:缓存模板中的一部分数据。只创建一次,以后就不会再更新了。也就是说用内存换取时间。一般用于前端搜索筛选。

<template>
  <div class="home">
    <input type="text" v-model="jiaoSheng">
    <!-- v-memo中值若不发生变化,则不会进行更新 -->
    <ul v-memo="[shouldUpdate]">
      <li class="licss" v-for="item in arr" :key="item">  {{ jiaoSheng }} -- {{ animalType[jiaoSheng] }}  </li>
    </ul>
  </div>
</template>
<script lang="ts" setup>
import { ref } from "@vue/reactivity"
import { watch } from "@vue/runtime-core"
const arr=new Array(10000)
const animalType={
  'mie':'🐏',
  'mo':'🐂',
  'miao':'🐱',
}
const jiaoSheng=ref('mie')
const shouldUpdate=ref(0)
// 监听jiaoSheng(输入框中的值)。
// 如果数据发生变化,并且在animalType对象中存在。试图进行更新。否则试图不进行更新。
watch(()=>jiaoSheng.value,()=>{
  if(Object.keys(animalType).includes(jiaoSheng.value)){
    shouldUpdate.value++
  }
})
</script>

五、useAttrs和useSlots

useAttrs 可以获取父组件传过来的id和class等值。 useSlots 可以获得插槽的内容

<!-- 父组件 -->
<template>
    <div class="father">{{ fatherRef }}</div>
    <Child :fatherRef="fatherRef" @changeVal="changeVal" class="btn" id="111">
      <template #test1>
        <div>1223</div>
      </template>
    </Child>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Child from "./Child.vue";
const fatherRef = ref("1");
function changeVal(val: string) {
    fatherRef.value = val;
}
</script>

<style lang="scss" scoped>
.father {
    margin-top: 40px;
    margin-bottom: 40px;
}
.btn {
    font-size: 20px;
    color: red;
}
</style>


<!-- 子组件 -->
<template>
    <div v-bind="attrs">
        <slot name="test1">11</slot>
        <input type="text" v-model="inputVal" />
    </div>
</template>

<script setup lang="ts">
import { computed, useAttrs, useSlots } from "vue";
const props = defineProps<{
    fatherRef: string;
}>();
const emits = defineEmits(["changeVal"]);
const slots = useSlots();
const attrs = useAttrs();
console.log(122, attrs, slots);
const inputVal = computed({
    get() {
        return props.fatherRef;
    },
    set(val: string) {
        emits("changeVal", val);
    },
});
</script>

<style lang="scss" scoped>
</style>

六、自定义指令

<script setup lang="ts">
const vMyFocus = {
  onMounted: (el: HTMLInputElement) => {
    el.focus();
    // 在元素上做些操作
  },
};
</script>
<template>
  <input v-my-focus value="111" />
</template>

番外:style v-bind

style v-bind将span变成红色

<template>
  <span> 有开始循环了-开端 </span>  
</template>
<script setup>
  import { reactive } from 'vue'
  const state = reactive({
    color: 'red'
  })
</script>
<style scoped>
  span {
    /* 使用v-bind绑定state中的变量 */
    color: v-bind('state.color');
  }  
</style>
目录
相关文章
|
10月前
|
JavaScript 前端开发 安全
Vue 3
Vue 3以组合式API、Proxy响应式系统和全面TypeScript支持,重构前端开发范式。性能优化与生态协同并进,兼顾易用性与工程化,引领Web开发迈向高效、可维护的新纪元。(238字)
1215 139
|
10月前
|
缓存 JavaScript 算法
Vue 3性能优化
Vue 3 通过 Proxy 和编译优化提升性能,但仍需遵循最佳实践。合理使用 v-if、key、computed,避免深度监听,利用懒加载与虚拟列表,结合打包优化,方可充分发挥其性能优势。(239字)
628 1
|
11月前
|
开发工具 iOS开发 MacOS
基于Vite7.1+Vue3+Pinia3+ArcoDesign网页版webos后台模板
最新版研发vite7+vue3.5+pinia3+arco-design仿macos/windows风格网页版OS系统Vite-Vue3-WebOS。
1104 11
|
10月前
|
JavaScript 安全
vue3使用ts传参教程
Vue 3结合TypeScript实现组件传参,提升类型安全与开发效率。涵盖Props、Emits、v-model双向绑定及useAttrs透传属性,建议明确声明类型,保障代码质量。
697 0
|
11月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
811 2
|
10月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
685 137
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
1488 0
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
JavaScript 数据可视化 前端开发
基于 Vue 与 D3 的可拖拽拓扑图技术方案及应用案例解析
本文介绍了基于Vue和D3实现可拖拽拓扑图的技术方案与应用实例。通过Vue构建用户界面和交互逻辑,结合D3强大的数据可视化能力,实现了力导向布局、节点拖拽、交互事件等功能。文章详细讲解了数据模型设计、拖拽功能实现、组件封装及高级扩展(如节点类型定制、连接样式优化等),并提供了性能优化方案以应对大数据量场景。最终,展示了基础网络拓扑、实时更新拓扑等应用实例,为开发者提供了一套完整的实现思路和实践经验。
1848 78
|
JavaScript 前端开发 开发者
Vue 自定义进度条组件封装及使用方法详解
这是一篇关于自定义进度条组件的使用指南和开发文档。文章详细介绍了如何在Vue项目中引入、注册并使用该组件,包括基础与高级示例。组件支持分段配置(如颜色、文本)、动画效果及超出进度提示等功能。同时提供了完整的代码实现,支持全局注册,并提出了优化建议,如主题支持、响应式设计等,帮助开发者更灵活地集成和定制进度条组件。资源链接已提供,适合前端开发者参考学习。
821 17