VUE3 VUE3:Typescript + 组合式API + setup语法糖
这里主要是来自b站尚硅谷VUE3的官方课堂笔记,有一些自己的修改。
介绍 vite
1 2 3 npm create vue@latest 创建项目 npm install 安装依赖 npm run dev 开启项目
目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13 . ├── README.md ├── env.d.ts //环境类型声明文件,定义文件类型 ├── index.html //应用的入口 HTML 文件 ├── node_modules //npm install下载的项目依赖 ├── package-lock.json //锁定依赖版本,确保每次安装依赖时的一致性。 ├── package.json //项目的配置文件 ├── public //存放静态资源(如图片、图标等)的文件夹 ├── src //源代码 ├── tsconfig.app.json //TypeScript 的配置文件 ├── tsconfig.json //定义 TypeScript 编译选项和编译范围。 ├── tsconfig.node.json // Node.js 环境的 TypeScript 编译设置。 └── vite.config.ts //Vite 的配置文件
vue渲染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 index.html <body> <div id="app"></div> //Vue 应用的挂载点。 <script type="module" src="/src/main.ts"></script> //解析 main.ts 文件,并执行其中的代码,初始化并挂载 Vue 应用。 </body> main.ts import './assets/main.css' // 引入根组件 App.vue import { createApp } from 'vue' //引入 Vue 3 的 createApp 函数 import App from './App.vue' //引入根组件 App createApp(App).mount('#app') // 创建应用实例并挂载到 #app 元素
.vue
文件可以由模板
、脚本
和样式
三部分组成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // 模板部分 <template> <div class="app"> //类名为app的组件容器 <h1>泥嚎:</h1> </div> </template> //脚本部分 <script lang="ts"> export default { name: 'App' //导出对象,为组件命名 } </script> //样式部分 <style> .app { //对 app 类的 CSS 类选择器。这个块中的样式将应用于类为 app 的 div 元素。 background-color: #0b1581; //颜色 box-shadow: 0 0 10px; //阴影的偏移和模糊半径 border-radius: 10px; //角半径,即边角圆滑程度 padding: 20px; //边框范围 } </style>
选项式API与组合式API
选项式API 在刚刚定义的组件添加一个子组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <template> <div class="app"> <h1>泥嚎:</h1> <person/> //添加子组件 </div> </template> <script lang="ts"> import Person from './components/Person.vue' export default { name: 'App', components: { // 注册了一个名为Person的组件 Person } } </script> <style> .app { background-color: #237849; box-shadow: 0 0 10px; border-radius: 10px; padding: 20px; } </style>
组合式API setup 将一个组件的不同逻辑功能放入一个setup()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 <template> <div class="person"> <h1>姓名: {{ name }}</h1> <h1>年龄: {{ age }}</h1> <h1>手机号: {{ tel }}</h1> <button @click="changename">>点击修改姓名</button> <button @mousemove="changeage">>点击修改年龄</button> <button @click="showTel">>点击查看联系方式</button> </div> </template> <script lang="ts"> export default { name: 'Person', setup() { //都未定义为响应式数据 let name = 'Randolfluo'; let age = 20; let tel = '123456789'; function changename() //不起作用,因为不是响应式数据 { name = 'miku'; } function changeage() //不起作用,因为不是响应式数据 { age += 1; } function showTel() //起作用,因为未作修改 { alert(tel); } return { name, age, tel, changename, changeage, showTel } //setup返回值,可以是渲染函数 //return()=> "114514" } }</script> <style scoped> .person { background-color: #e0eee7; box-shadow: 0 0 10px; border-radius: 10px; padding: 20px; } button { background-color: rgb(160, 183, 212); border-radius: 1000px; margin: 0 10px; } </style>
setup语法糖 我们可以将setup
单独放入一个script
标签,直接返回该标签内所有元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <script lang="ts"> export default { name: 'Person' }</script> <script lang="ts" setup> let name = 'Randolfluo'; let age = 20; let tel = '123456789'; function changename() //不起作用,因为不是响应式数据 { name = 'miku'; } function changeage() //不起作用,因为不是响应式数据 { age += 1; } function showTel() //起作用,因为未作修改 { alert(tel); } </script>
ref&reactive
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <template> <div class="person"> <h1>姓名: {{ user.username }}</h1> <h1>年龄: {{ user.age }}</h1> <h1>手机号: {{ user.tel }}</h1> <button @click="changeage">>点击修改年龄</button> <h1>game:</h1> <ul> <li v-for="g in game" :key="g.id">{{ g.name }}</li> //v-for 指令用于基于一个数组渲染列表。当数组中的对象发生变化时,Vue 会自动更新列表中的元素。 </ul> <button @click="yuanshenqidong">>点击启动!</button>" </div> </template> <script lang="ts"> export default { name: 'Person' }</script> <script lang="ts" setup> import { reactive, ref } from 'vue'; let user = reactive({ username: 'Randolfluo', age: 20, tel: '123456789' }); let game = ref([ {id:'game1', name:'red alarm'}, {game2:'game2', name:'warthunder'}, {game3: 'game3', name:'MC'} ]); function changeage() { user.age += 1; } function yuanshenqidong(){ game.value.forEach(item => { item.name = '原神启动'; }); } </script>
toRefs与toRef
1 2 3 4 5 6 let person = reactive({ name: 'Randolfluo', age : 20; }) let{name, age} = toRefs(person) let ag = toRef(person,'age')
compuuted计算属性
v-bind
单向绑定意味着数据只能从父组件流向子组件,而不能反向流动。
v-model
双向绑定意味着数据可以从父组件流向子组件,也可以从子组件反向流向父组件。
computed计算属性实际是ref定义的响应数据
默认computed是只读的缓存,我们可以添加get
和set
方法来返回和设置值实现读写权限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <template> <div class="person"> firstname: <input type="text" v-model="firstname"> <br> lastname: <input type="text" v-model="lastname"> <br> <button @click="Mikumiku">我推的:</button> <br> fullname: <span> {{ fullname }}</span> </div> </template> <script lang="ts"> export default { name: 'Person' }</script> <script lang="ts" setup> import { ref,computed } from 'vue'; let firstname = ref('randolf'); let lastname = ref('luo'); // let fullname = computed(()=>{ // return firstname.value.slice(0,1).toUpperCase() + firstname.value.slice(1) + '-' + lastname.value; // }); let fullname = computed({ get(){ return firstname.value.slice(0,1).toUpperCase() + firstname.value.slice(1) + '-' + lastname.value; }, set(val){ //Mikumiku函数修改触发set const [str1, str2] = val.split('-'); firstname.value = str1; lastname.value = str2; } }) function Mikumiku(){ fullname.value = 'Hatsune-Miku' } </script>
watch监视 Vue3
中的watch
只能监视以下四种数据 :
ref
定义的数据。
reactive
定义的数据。
函数返回一个值(getter
函数)。
一个包含上述内容的数组。
监视ref
定义的【基本类型】数据
1 2 3 4 5 const stopWatch = watch(sum,(newValue,oldValue)=>{ console.log('sum变化了',newValue,oldValue) if(newValue >= 10){ stopWatch() }
监视ref
定义的【对象类型】数据,监视的是对象的【地址值】,监视该对象的值需要开启深度监视(deep)
1 2 3 watch(person,(newValue,oldValue)=>{ console.log('person变化了',newValue,oldValue) },{deep:true})
监视reactive
定义的【对象类型】数据,默认开启了深度监视(隐式创建深层监听 )。
1 2 3 watch(person,(newValue,oldValue)=>{ console.log('person变化了',newValue,oldValue) })
监视ref
或reactive
定义的【对象类型】数据中的某个属性 ,注意点如下:
若该属性值不是 【对象类型】,需要写成函数形式。
若该属性值是依然 是【对象类型】,可直接编,也可写成函数,建议写成函数。
结论:监视的要是对象里的属性,那么最好写函数式,注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视。
1 2 3 4 5 6 7 8 watch(()=> person.name,(newValue,oldValue)=>{ console.log('person.name变化了',newValue,oldValue) }) watch(()=>person.car,(newValue,oldValue)=>{ console.log('person.car变化了',newValue,oldValue) },{deep:true})
监视上述的多个数据
1 2 3 watch([()=>person.name,person.car],(newValue,oldValue)=>{ console.log('person.car变化了',newValue,oldValue) },{deep:true})
watchEffect:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。
1 2 3 4 5 6 7 8 9 10 11 12 const stopWtach = watchEffect(()=>{ // 室温达到50℃,或水位达到20cm,立刻联系服务器 if(temp.value >= 50 || height.value >= 20){ console.log(document.getElementById('demo')?.innerText) console.log('联系服务器') } // 水温达到100,或水位达到50,取消监视 if(temp.value === 100 || height.value === 50){ console.log('清理了') stopWtach() } })
标签的ref属性 为什么不用javascript引用标签
因为一个页面不能有多个一样的id,但是可以存在多个相同的类 。若父类和子类定义相同的id,则锚点链接可能无法正确工作。
作用:用于模板引用作用:用于注册模板引用。
类似于局部变量
局部样式: