Vue3.2单文件组件setup的语法糖总结

目录

前言

setup语法糖

一、基本用法

二、data和methods

三、计算属性computed

四、监听器watch、watchEffect

五、自定义指令directive

六、import导入的内容可直接使用

七、声明props和emits 

八、父组件获取子组件的数据

 九、provide和inject传值

十、路由useRoute和useRouter

十一、对await异步的支持

十二、nextTick

十三、全局属性globalProperties

十四、生命周期

十五、与普通的script标签一起使用

十六、v-memo新指令

style新特性

一、局部样式

二、深度选择器

三、插槽选择器

四、全局选择器

五、混合使用局部与全局样式

六、支持CSS Modules

七、与setup一同使用

八、动态 CSS


前言

        满满的干货,建议收藏慢慢看,可以当作Vue3.0的学习资料。

        在vue2.0时期,组件里定义的各类变量、方法、计算属性等是分别存放到data、methods、computed...选项里,这样编写的代码不便于后期的查阅(查找一个业务逻辑需要在各个选项来回切换)。setup函数的推出就是为了解决这个问题,让新手开发者更容易上手...

setup语法糖

        setup是Vue3.0后推出的语法糖,并且在Vue3.2版本进行了大更新,像写普通JS一样写vue组件,对于开发者更加友好了;按需引入computed、watch、directive等选项,一个业务逻辑可以集中编写在一起,让代码更加简洁便于浏览。

一、基本用法

只需在<script>里添加一个setup属性,编译时会把<script setup></script>里的代码编译成一个setup函数

<script setup>
console.log('hello script setup')
</script>

普通的<script>只会在组件被首次引入的时候执行一次,<script setup>里的代码会在每次组件实例被创建的时候执行

二、data和methods

<script setup>里声明的变量和函数,不需要return暴露出去,就可以直接在template使用

<script setup>
import { ref, reactive } from 'vue'    
// 普通变量
const msg = 'Hello!'// 响应式变量
let num = ref(1111)         // ref声明基本类型变量
const obj = reactive({        // reactive声明对象类型变量,如Object、Array、Date...key: 'this is a object'
})// 函数
function log() {console.log(msg)          // Helloconsole.log(num.value)    // 1111(可根据input输入值而改变)console.log(obj.key)      // this is a object
}
</script><template><h1>{{ msg }}</h1><p>{{obj.key}}</p><input v-model="num" type="text" /><button @click="log">打印日志</button>
</template>

三、计算属性computed

<script setup>
import { ref, computed } from 'vue'let count = ref(0)
const countPlus = computed(()=>{return count.value+1
})
</script><template><h1>计数:{{ countPlus }}</h1>
</template>

四、监听器watch、watchEffect

1、watch监听器除了使用方式有区别之外,其他的与vue2.0没啥变化

<script setup>
import { ref, reactive, watch } from 'vue'// 监听ref
let count = ref(0)
watch(count, (newVal, oldVal)=> {console.log('修改后', newVal)console.log('修改前', oldVal)
})// 监听reactive属性
const obj = reactive({count: 0
})
watch(()=> obj.count,     // 一个函数,返回监听属性(newVal, oldVal)=> {console.log('修改后', newVal)console.log('修改前', oldVal)},{immediate: true,     // 立即执行,默认为falsedeep: true     // 深度监听,默认为false}
)const onChange = function(){count.value++obj.count++
}
</script><template><button @click="onChange">改变count</button>
</template>

2、watchEffect

watchEffect是Vue3.0新增的一个监听属性的方法,它与watch的区别在于watchEffect不需要指定监听对象,回调函数里可直接获取到修改后的属性的值

<script setup>
import { ref, reactive, watchEffect } from 'vue'let count = ref(0)
const obj = reactive({count: 0
})
setTimeout(()=>{count.value++obj.count++
}, 1000)watchEffect(()=> {console.log('修改后的count', count.value)console.log('修改前的obj', obj.value)
})
</script>

五、自定义指令directive

以 vNameOfDirective 的形式来命名本地自定义指令,可以直接在模板中使用

<script setup>
// 导入指令可重命名
// import { myDirective as vMyDirective } from './MyDirective.js'// 自定义指令
const vMyDirective = {beforeMount: (el) => {// 在元素上做些操作}
}
</script>
<template><h1 v-my-directive>This is a Heading</h1>
</template>

六、import导入的内容可直接使用

 1、导入的模块内容,不需要通过 methods 来暴露它

// utils.js 
export const onShow = function(name) {return 'my name is ' + name
}
// Show.vue
<script setup>import { onShow } from './utils.js'
</script>
<template><div>{{ onShow('jack') }}</div>
</template>

 2、导入外部组件,不需要通过components注册使用

// Child.vue
<template><div>I am a child</div>
</template>
// Parent.vue
<script setup>import Child from './Child.vue'
</script>
<template><child></child>
</template>

七、声明props和emits 

在 <script setup> 中必须使用 defineProps 和 defineEmits API 来声明 props 和 emits ,它们具备完整的类型推断并且在 <script setup> 中是直接可用的

// Child.vue
<script setup>// 声明props
const props = defineProps({info: {type: String,default: ''}
})// 声明emits
const $emit = defineEmits(['change'])const onChange = function() {$emit('change', 'child返回值')
}
</script><template><h1>信息:{{ info }}</h1><button @click="onChange">点击我</button>
</template>
// Parent.vue
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'const msg = ref('hello setup !')    // 响应式变量const onAction = function(event) {console.log(event)    // child返回值
}
</script><template><child :info="msg" @change="onAction"></child>
</template>

如果使用了 Typescript,使用纯类型声明来声明 prop 和 emits 也是可以的。

八、父组件获取子组件的数据

父组件要想通过ref获取子组件的变量或函数,子组件须使用defineExpose暴露出去

// Child.vue
<script setup>
import { ref, defineExpose } from 'vue'const info = ref('I am child')
const onChange = function() {console.log('Function of child')
}// 暴露属性
defineExpose({info,onChange
})
</script><template><h1>信息:{{ info }}</h1><button @click="onChange">点击我</button>
</template>
// Parent.vue
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'const childRef = ref()
const onAction = function() {console.log(childRef.value.info)    // I am childconsole.log(childRef.value.onChange())    // Function of child
}
</script><template><child ref="childRef"></child><button @click="onAction">获取子值</button>
</template>

 九、provide和inject传值

无论组件层次结构有多深,父组件都可以通过provide 选项来其所有子组件提供数据,子组件通过inject接收数据

// Parent.vue
<script setup>
import { ref, provide } from 'vue'
import Child from './Child.vue'const msg = ref('Hello, my son')
const onShow = function() {console.log('I am your parent')
}provide('myProvide', {msg,onShow
})
</script><template><child></child>
</template>
// Child.vue
<script setup>
import { inject } from 'vue'const provideState = inject('myProvide')    // 接收参数const getData = function() {console.log(provideState.msg)    // Hello, my sonconsole.log(provideState.onShow())    // I am your parent
}
</script><template><button @click="getData">获取父值</button>
</template>

十、路由useRoute和useRouter

<script setup>
import { useRoute, useRouter } from 'vue-router'const $route = useRoute()
const $router = userRouter()// 路由信息
console.log($route.query)// 路由跳转
$router.push('/login')
</script>

十一、对await异步的支持

<script setup> 中可以使用顶层 await。结果代码会被编译成 async setup()

<script setup>const post = await fetch(`/api/post/1`).then(r => r.json())
</script>

十二、nextTick

// 方式一
<script setup>
import { nextTick } from 'vue'nextTick(()=>{console.log('Dom已更新!')
})
</script>
// 方式二
<script setup>
import { nextTick } from 'vue'await nextTick()    // nextTick是一个异步函数,返回一个Promise实例
// console.log('Dom已更新!')
</script>

十三、全局属性globalProperties

// main.js里定义
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)// 定义一个全局属性$global 
app.config.globalProperties.$global = 'This is a global property.' app.mount('#app')
// 组件内使用
<script setup>
import { getCurrentInstance } from 'vue'// 获取vue实例
const { proxy } = getCurrentInstance()
// 输出
console.log(proxy.$global)    // This is a global property.
</script>

十四、生命周期

setup()里访问组件的生命周期需要在生命周期钩子前加上“on”,并且没有beforeCreate和created生命周期钩子

因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。

// 使用方式
<script setup>
import { onMounted } from 'vue'onMounted(()=> {console.log('onMounted')
})
</script>

十五、与普通的script标签一起使用

<script setup> 可以和普通的 <script> 一起使用。普通的 <script> 在有这些需要的情况下或许会被使用到:

  • 无法在 <script setup> 声明的选项,例如 inheritAttrs 或通过插件启用的自定义的选项;
  • 声明命名导出,<script setup>定义的组件默认以组件文件的名称作为组件名;
  • 运行副作用或者创建只需要执行一次的对象。
<script>
// 普通 <script>, 在模块范围下执行(只执行一次)
runSideEffectOnce()// 声明额外的选项
export default {name: 'ComponentName',    // 组件重命名inheritAttrs: false,customOptions: {}
}
</script><script setup>
// 在 setup() 作用域中执行 (对每个实例皆如此)
</script>

十六、v-memo新指令

该指令与v-once类似,v-once是只渲染一次之后的更新不再渲染,而v-memo是根据条件来渲染。该指令接收一个固定长度的数组作为依赖值进行记忆比对,如果数组中的每个值都和上次渲染的时候相同,则该元素(含子元素)不刷新。

1、应用于普通元素或组件;

<template>
<-- 普通元素 -->
<div v-memo="[valueA, valueB]">... 
</div><-- 组件 -->
<component v-memo="[valueA, valueB]"></component>
</template><script setup>
import component from "../compoents/component.vue"
</script>

当组件重新渲染的时候,如果 valueA 与 valueB 都维持不变,那么对这个 <div> 以及它的所有子节点的更新都将被跳过。

2、结合v-for使用

v-memo 仅供性能敏感场景的针对性优化,会用到的场景应该很少。渲染 v-for 长列表 (长度大于 1000) 可能是它最有用的场景:

<template>
<div v-for="item in list" :key="item.id" v-memo="[item.id === selected]"><p>ID: {{ item.id }} - selected: {{ item.id === selected }}</p><p>...more child nodes</p>
</div>
</template>

当selected发生变化时,只有item.id===selected的该项重新渲染,其余不刷新。

style新特性

Vue3.2版本对单文件组件的style样式进行了很多升级,如局部样式、css变量以及样式暴露给模板使用等。

一、局部样式

当 <style> 标签带有 scoped attribute 的时候,它的 CSS 只会应用到当前组件的元素上:

<template><div class="example">hi</div>
</template><style scoped>
.example {color: red;
}
</style>

二、深度选择器

处于 scoped 样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用 :deep() 这个伪类:

<style scoped>
.a :deep(.b) {/* ... */
}
</style>

通过 v-html 创建的 DOM 内容不会被作用域样式影响,但你仍然可以使用深度选择器来设置其样式。

三、插槽选择器

默认情况下,作用域样式不会影响到 <slot/> 渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。使用 :slotted 伪类以确切地将插槽内容作为选择器的目标:

<style scoped>
:slotted(div) {color: red;
}
</style>

四、全局选择器

如果想让其中一个样式规则应用到全局,比起另外创建一个 <style>,可以使用 :global 伪类来实现:

<style scoped>
:global(.red) {color: red;
}
</style>

五、混合使用局部与全局样式

你也可以在同一个组件中同时包含作用域样式和非作用域样式:

<style>
/* global styles */
</style><style scoped>
/* local styles */
</style>

六、支持CSS Modules

<style module> 标签会被编译为 CSS Modules 并且将生成的 CSS 类键暴露给组件:

1、 默认以$style 对象暴露给组件;

<template><p :class="$style.red">This should be red</p>
</template><style module>
.red {color: red;
}
</style>

2、可以自定义注入module名称

<template><p :class="classes.red">red</p>
</template><style module="classes">
.red {color: red;
}
</style>

七、与setup一同使用

注入的类可以通过 useCssModule API 在 setup() 和 <script setup> 中使用:

<script setup>
import { useCssModule } from 'vue'// 默认, 返回 <style module> 中的类
const defaultStyle = useCssModule()// 命名, 返回 <style module="classes"> 中的类
const classesStyle = useCssModule('classes')
</script>

八、动态 CSS

单文件组件的 <style> 标签可以通过 v-bind 这一 CSS 函数将 CSS 的值关联到动态的组件状态上:

<script setup>
const theme = {color: 'red'
}
</script><template><p>hello</p>
</template><style scoped>
p {color: v-bind('theme.color');
}
</style>

(完) 

参考文献:

SFC 语法规范 | Vue.js

Vue3.2 setup语法糖、Composition API、状态库Pinia归纳总监


---------------------
作者:用户体验官大龙
来源:CSDN
原文:https://wiill.blog.csdn.net/article/details/124554063
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283471.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用dotnet-monitor分析在Kubernetes的应用程序:Sidecar模式

dotnet-monitor可以在Kubernetes中作为Sidecar运行&#xff0c;Sidecar是一个容器&#xff0c;它与应用程序在同一个Pod中运行&#xff0c;利用Sidecar模式使我们可以诊断及监控应用程序。如下图所示&#xff0c;这是我们最终要实现的目标&#xff0c;通过可视化界面查看应用程…

SFB 项目经验-07-Skype for Business 话机 Polycom CX700

本系列博文&#xff1a;Lync 项目经验-01-共存迁移-Lync2013-TO-SFB 2015-规划01http://dynamic.blog.51cto.com/711418/1858520 Lync 项目经验-02-共存迁移-Lync2013-TO-SFB 2015-规划02http://dynamic.blog.51cto.com/711418/1859143 Lync 项目经验-03-共存迁移-Lync2013-TO…

亿方云CEO程远:转型第一式:链接企业人与数据

传统企业一直在探讨如何做好互联网转型&#xff0c;那么互联网核心是什么&#xff1f;转型目标是什么&#xff1f;亿方云CEO程远在此次峰会上发表了自己看法&#xff0c;他认为快、人、连接是互联网核心基因&#xff0c;转型第一步就在于企业、人与数据的充分链接。中国企业的互…

使用.NET简单实现一个Redis的高性能克隆版(七-完结)

译者注该原文是Ayende Rahien大佬业余自己在使用C# 和 .NET构建一个简单、高性能兼容Redis协议的数据库的经历。首先这个"Redis"是非常简单的实现&#xff0c;但是他在优化这个简单"Redis"路程很有趣&#xff0c;也能给我们在从事性能优化工作时带来一些启…

解决 Vue 里 Script 标签首层不缩进 - VS Code

问题&#xff1a; 在 vscode 使用 vue 的时候&#xff0c;发现 script 标签首层不缩进&#xff1f;&#xff1f;&#xff1f; 下载扩展&#xff1a;prettier 解决方法一&#xff1a; 打开 setting.json文件 添加&#xff1a;"prettier.vueIndentScriptAndStyle": tru…

Android应用开发性能优化完全分析

1 背景 其实有点不想写这篇文章的&#xff0c;但是又想写&#xff0c;有些矛盾。不想写的原因是随便上网一搜一堆关于性能的建议&#xff0c;感觉大家你一总结、我一总结的都说到了很多优化注意事项&#xff0c;但是看过这些文章后大多数存在一个问题就是只给出啥啥啥不能用&am…

ZBLOG-ASP2.2如何给图片增加ALT标签说明文字?

2019独角兽企业重金招聘Python工程师标准>>> 一直以来&#xff0c;我们在建设网站的时候&#xff0c;都容易犯下一个大错误&#xff0c;那就是没有重视图片的文字说明&#xff0c;而大多数时候&#xff0c;技术方面并不能很好的识别图片的内容&#xff0c;这也是受限…

[asp.net mvc 奇淫巧技] 04 - 你真的会用Action的模型绑定吗?

在QQ群或者一些程序的交流平台&#xff0c;经常会有人问&#xff1a;我怎么传一个数组在Action中接收、我传的数组为什么Action的model中接收不到、或者我在ajax的data中设置了一些数组&#xff0c;为什么后台还是接收不了、还有一些怎么传送一个复杂的对象或者Action怎么接收一…

拒绝“高冷”词汇!初学C#中的委托

拒绝“高冷”词汇&#xff01;初学C#中的委托 有一天&#xff0c;你写了好多好多带“形参”的构造函数&#xff08;就是“方法”&#xff0c;同义&#xff09;&#xff0c;而且需要向这些构造函数里传递同样的“实参”&#xff0c;然后你就憨憨地一个一个函数的调用并赋予同样的…

JAVA企业级应用TOMCAT实战视频课程

1. Tomcat简介Tomcat是Apache软件基金会&#xff08;Apache Software Foundation&#xff09;的Jakarta 项目中的一个核心项目&#xff0c;由Apache、Sun和其他一些公司及个人共同开发而成。Tomcat服务器是一个免费的开放源代码的Web应用服务器&#xff0c;属于轻量级应用服务器…

WPF 系列-01默认程序结构

WPF应用程序启动项创建一个WPF应用程序&#xff0c;系统为我们自动生成了App.xaml和一个普通的MainWindow.xaml窗体文件。App.xaml 和cs 文件文件如下&#xff1a;<Application x:Class"Example_01.App"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/…

纳税服务系统【角色与用户】

用户与角色之间的关系 我们在做用户模块的时候&#xff0c;漏掉了最后一个功能。在新增功能中是可以选择角色的。 用户与角色之间的关系也是多对多 一个用户对应多个角色一个角色可以被多个用户使用。现在呢&#xff0c;我们的用户表已经是写的了。我们最好就不要修改原有的用户…

flex-grow flex-shrink 解决最后一行个数不足无法对齐

正常情况下&#xff0c;每页大小15个&#xff0c;设置每行3列&#xff0c;刚好5行。 当外部容器宽度不足以放3列时&#xff0c;自动换行&#xff0c;但最后一行元素自动撑满 &#xff0c;会造成元素块大小不一致&#xff0c;不是想要的效果 原始代码示例&#xff1a; <ul …

C# 并行编程避坑指南之-Try Catch系列

自从.NET Framework 4.5(含4.5)提供了Task开启线程后&#xff0c;基本上Thread的使用频率就大幅度降低了&#xff0c;但是一些老项目&#xff0c;或者老程序还是习惯用Thread去做&#xff0c;如果一定要使用Thred&#xff0c;那我们就必须在代码中使用try、catch块去处理异常的…

spring boot 整合mybatis

1、添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>com.oracle</groupId><artifactId>ojdbc6</art…

k8s 读书笔记 - CRI(容器运行时接口)详解

k8s Node 节点&#xff08;kubelet&#xff09;的主要功能就是启动和停止容器的组件&#xff0c;这组件我们称之为 容器运行时&#xff08;Container Runtime&#xff09;&#xff0c;这其中最知名的就是 Docker 了。为了更具扩展性&#xff0c;k8s 从 v1.5 版本开始就加入了容…

Win11的这个功能,厉害了!

上周微软正式发布了Windows11的22H2版本&#xff0c;虽说是一周年更新版&#xff0c;但仍然有不少的问题。微软给Win10换了一套皮肤&#xff0c;并做了一些优化升级&#xff0c;摇身一变成了Win11&#xff0c;但是外观方面却做的并不是很协调&#xff0c;有一些界面仍然保留着以…

MAUI + Masa Blazor 开发带自动更新功能的安卓App

自动更新主要下面4个步骤获取最新版本号提示用户发现更新&#xff0c;等待用户确认更新下载最新的apk包安装apk包下面从创建MAUI项目开始1、创建Maui Blazor Server应用2、安装Masa.Blazor&#xff0c;并添加引用dotnet add package Masa.Blazor在 wwwroot/index.html 中引入资…

[deviceone开发]-一个很炫的手势动画示例

2019独角兽企业重金招聘Python工程师标准>>> 一、简介 这是iOS下的效果&#xff0c;android下完全一致。通过do_GestureView组件和do_Animation组件&#xff0c;deviceone能很容易实现复杂的跨平台纯原生动画效果,这个示例就是通过手势控制图片上下动画滑动实现开合…

POJ-3067 Japan---树状数组逆序对变形

题目链接&#xff1a; https://vjudge.net/problem/POJ-3067 题目大意&#xff1a; 日本岛东海岸与西海岸分别有N和M个城市&#xff0c;现在修高速公路连接东西海岸的城市&#xff0c;求交点个数。 解题思路&#xff1a; 记每条告诉公路为(x,y), 即东岸的第x个城市与西岸的第y个…