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>
目录
相关文章
|
18天前
vue3学习(3)
vue3学习(3)
|
15天前
|
JavaScript API
Vue3中的计算属性能否动态修改
【9月更文挑战第5天】Vue3中的计算属性能否动态修改
49 10
|
8天前
|
JavaScript
Vue3中路由跳转的语法
Vue3中路由跳转的语法
111 58
|
11天前
|
前端开发
vue3+ts项目中使用mockjs
vue3+ts项目中使用mockjs
216 58
|
1天前
|
存储 API
vue3中如何动态自定义创建组件并挂载
vue3中如何动态自定义创建组件并挂载
|
6天前
|
JavaScript 索引
Vue 2和Vue 3的区别以及实现原理
Vue 2 的响应式系统通过Object.defineProperty来实现,它为对象的每个属性添加 getter 和 setter,以便追踪依赖并响应数据变化。
22 9
|
8天前
|
JavaScript 开发工具
vite如何打包vue3插件为JSSDK
【9月更文挑战第10天】以下是使用 Vite 打包 Vue 3 插件为 JS SDK 的步骤:首先通过 `npm init vite-plugin-sdk --template vue` 创建 Vue 3 项目并进入项目目录 `cd vite-plugin-sdk`。接着,在 `src` 目录下创建插件文件(如 `myPlugin.js`),并在 `main.js` 中引入和使用该插件。然后,修改 `vite.config.js` 文件以配置打包选项。最后,运行 `npm run build` 进行打包,生成的 `my-plugin-sdk.js` 即为 JS SDK,可在其他项目中引入使用。
|
9天前
|
JavaScript 开发者
彻底搞懂 Vue3 中 watch 和 watchEffect是用法
彻底搞懂 Vue3 中 watch 和 watchEffect是用法
|
15天前
|
JavaScript API
如何使用Vue3的可计算属性
【9月更文挑战第5天】如何使用Vue3的可计算属性
44 13
|
6天前
|
JavaScript 调度
Vue3 使用 Event Bus
Vue3 使用 Event Bus
11 1