# Vue3.0 万字基础篇
补充:
# 1. 过滤器的使用
连续调用
第一个值会传给第二个过滤器里面的第一个参数,第二个过滤器处理完后返回值在第三个过滤器里面也可以拿到进行处理。
传参,接受参数顺序位置
1 2 3 4 5 6 7 8 9
| {{message|filter(a,b)}} 接受值 Vue.filter(filter,(message,a,b)=>{ })
|
# 单页面应用的缺点
1. 路由懒加载
2. 代码压缩
3.cdn 加速,网络传输压缩
导致首屏加载慢。
不利于 SEO (ssr 服务器端渲染)
# 创建单页面应用程序的方式:
1.vite
仅支持 vue3.x 不基于 webpack, 运行速度快,小
2.vue-cli
大而全,基于 webpack,支持 vue2 和 3
# 基于 vite 创建 vue 项目
创建并初始化项目
1 2 3 4 5 6 7 8
| npm init vite-app code1//1 cd code1 //2 npm install //3 4.npm run dev
|
通过 main.js 把 App.vue 渲染到 index.html 的指定区域
App.vue 用来编写待渲染的模板结构,index.html 预留了 id 为 app 的区域用来渲染 app.vue
# 1. 在 main.js 中有和 vue2 不一样的东西
从 vue 中按需导入 createApp 函数,用来创建 vue 的 “单页面应用程序实例”,就是 vue 实例
1
| import { createApp } from 'vue'
|
导入 App 组件并且把组件渲染到 vue 实例里面,mount ('#app')==el:'app', 绑定 id=app 指定 vue 实例控制的区域,把 app.vue 渲染到实际控制区域
1 2
| import App from './App.vue' createApp(App).mount('#app')
|
组件化开发:把页面上可重用的部分封装为组件,方便开发和维护
每个 vue 组件都由 template 模板结构,script,style 样式组成
# template 是容器不会被渲染到页面,vue3 和 vue2 中 template 的区别
1.vue2 中 template 只支持单个根节点,但是 vue3 中支持多个根节点
在 vue2 中 template 节点内的元素必须包一层 div 否则报错,但是 vue3 中并不需要,也可以包裹
script 中的 name 属性自定义的组件名在使用 vue-devtools 进行项目调试的时候可以清晰区分每个组件
data 节点:组件中的 data 节点只能以函数形式 return 不能以对象形式储存数据
组件:通过 name 属性注册组件,
之前在全局注册的时候都是使用自定义组件名的方式来定义标签名
1
| Vue.component('MyApp',MyApp)
|
也可以直接使用组件的 name 属性来注册
1
| Vue.component(MyApp.name,MyApp)
|
组件样式冲突问题
在 style 标签上使用 scoped 属性解决组件样式冲突问题,原理就是 scoped 属性会给每个便签都添加自定义属性来解决样式冲突问题
/deep/ 加在有些需要控制子组件某些样式时候可以使用这个属性:
这样就可以突破 scoped 的封锁线冲出去寻找他的儿子了,vue3 里用:deep () 来代替 /deep/
props: 父传子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 子组件中 export default{ name:'MyHellow' props:{ msg:String } } 父组件 <MyHellow msg='我是父组件传过来的值' /> 或者 <MyHellow :msg='daya' /> data(){ return{ daya:''我是父组件传过来的值' } }
|
prop 参数值的命名规则
1 2 3 4 5 6 7
| props:{ pubName:String } 父组件传值可以以 pubName='' 或者 pub-name=''
|
# Class 和 Style 的绑定
通过 v-bind 可以绑定 class 的类名
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> <!-- <MyDream></MyDream> --> <h1 :class="isFalse ? 'newClas' : ''">我是class测试组件</h1> <button @click="isFalse = !isFalse">点我变身</button> </template> <script> import MyDream from './components/MyDream.vue' export default { name: 'App', components: { MyDream }, data() { return { isFalse: false } } } </script> <style lang="less"> .newClas { color: hotpink; font-size: 500px; } </style>
|
数组语法绑定多个 class 类名
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
| <template> <!-- <MyDream></MyDream> --> <h1 :class="[isFalse ? 'newColor' : '', isBig ? 'big' : '']"> 我是class测试组件 </h1> <button @click="isFalse = !isFalse">点我变颜色</button> <button @click="isBig = !isBig">点我变歪</button> </template> <script> import MyDream from './components/MyDream.vue' export default { name: 'App', components: { MyDream }, data() { return { isFalse: false, isBig: false } } } </script> <style lang="less" scoped> .newColor { color: hotpink; } .big { font-style: oblique; } </style>
|
# 对象语法绑定 class, 因为以数组形式绑定 class 会使模板可读性遍地,性能也会受影响
布尔值的名字要和类名一样才可以
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
| <template> <!-- <MyDream></MyDream> --> <!-- <h1 :class="[isFalse ? 'newColor' : '', isBig ? 'big' : '']"> 我是class测试组件 </h1> <button @click="isFalse = !isFalse">点我变颜色</button> <button @click="isBig = !isBig">点我变大</button> --> <h1 :class="classObj">我是class测试组件</h1> <button @click="classObj.isFalse = !classObj.isFalse">点我变颜色</button> <button @click="classObj.isBig = !classObj.isBig">点我变大</button> </template> <script> import MyDream from './components/MyDream.vue' export default { name: 'App', components: { MyDream }, data() { return { classObj: { isFalse: false, isBig: false } } } } </script> <style lang="less" scoped> .isFalse { color: hotpink; } .isBig { font-style: oblique; } </style>
|
# 动态绑定 style
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <h1 :style="{ color: active, 'font-size': font + 'px' }">我是一对象</h1> <button @click="font++">+1</button> <button @click="font--">-1</button> </template> <script> import MyDream from './components/MyDream.vue' export default { name: 'App', components: { MyDream }, data() { return { font: 24, active: 'red' } } }
|
# props 验证
1 2 3 4 5 6 7 8 9 10 11 12
| props:{ msg:String num:[Number,String,Boolean,Array,Object,Date,Function,Symbol] num1:{ type:[Number,String,Boolean,Array,Object,Date,Function,Symbol], require:true default:123 } }
|
自定义验证函数
1 2 3 4 5 6 7 8 9
| props:{ num:{ validator(value){ 验证num是不是等于数组中的任何一个值, return ['Number','String','Array'].indexOf(value)!=-1 } } }
|
还可以使用 instandOf 来验证数据类型
# 计算属性・1
实时监听 data 中的数据变化,并 return 返会一个计算后的新值。
计算属性相对于方法来说,计算属性会缓存计算的结果,只有依赖项数据发生变化时才会重新计算
# 自定义事件
1. 声明自定义事件
创建 button 设置单击事件 add
1 2 3 4
| add(){ this.count++ this.$emit('numChange') }
|
在父组件监听事件触发
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @numChage='getCount' getCount(){ cl(触发了numchange) }
|
传参在 $emit () 中第二个参数可以传参
1
| this.$emit('numChange',count)
|
组件上使用 v-model: 子组件值发生改变同步到父组件,父组件值发生改变同步到子组件
父向子同步数据
1. 父组件通过 v-bind 向子组件传递数据,子组件通过 props 接收父组件传过来的值
1 2 3 4 5 6 7 8 9
| <myDream :msg='counts'></myDream> props:{ counts:{ type:[string,num] } }
|
2. 子向父同步数据
1. 在父组件 v-bind 前添加 v-model
1
| <MyDream v-model:counter="font"></MyDream>
|
2. 在子组件添加 $emit ('update:counter',this.counter+1)
3. 父组件 v-bind 前加 v-model 这样就双向绑定了 counter 和 font
![]()
# watch 监听器
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
| watch:{ username(newVal,oldVal){ } } watch:{ username:{ handler(newVal,oldVal){ } immediate:true deep:true } }
watch:{ 'username.name':{ handler(newVal,oldVal){ } immediate:true deep:true } }
|
计算属性和监听器侧重不同,计算属性侧重监听多个值的变化,计算并返回最终的值,
watch 侧重于单个数据的变化,最终执行特定的任务去执行,不需要返回值
# 组件的生命周期
运行:import 导入 component 注册标签使用,在内存实例中创建对象,把创建的实例渲染到页面,组件切换时销毁需要被隐藏的组件
主要生命周期
created: 组件在内存中创建完毕,一个生命周期只执行一次,可以在这里发起 ajax 请求初始化
mounted: 组件在页面被渲染后,执行一次,可以操作 Dom 元素
update: 组件在页面中被重新渲染后,0 或多次
unmounted:组件被销毁(页面和内存)后,一次
# 组件之间的数据共享
1. 父 ---> 子
1 2 3 4 5 6 7 8
| <父组件里面的子组件标签 :name='username'> 子 props:{ name:String }
|
2. 子 --> 父
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 子组件 emits:['numAdd'] add() { this.$emit('numAdd',this.num) } <父组件中的子组件 @numAdd='addNew'> addNew(val){
}
|
3. 父 <-> 子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <父组件中的子组件 v-model:num='count'> 子组件 emits:['update:num'] props:{ num:Number } this.$emit('update:num',this.number+1)
|
4.EventBus 全局事件总线
第三方包 mitt,
创建 EventBus.js
1 2 3 4 5 6 7
| import mitt from'mitt' const bus=mitt() export default bus
|
在两个兄弟组件中引入
1
| import bus from'./EventBus'
|
发送数据方
1 2 3 4 5 6 7
| methods: addNum(){ bus.emit('countChange',this.count) }
|
接受方在 created 中接受
1 2 3 4 5 6 7 8
| created: bus.on('countChange',(count)=>{ this.num=count cl(count) })
|
后代数据共享
父:
1 2 3 4 5 6 7 8
| data(){ num:1 }, provide(){ return{ num:this.num } }
|
后代:
接收后就可以直接使用,
共享响应式数据父组件数据改变后代组件也改变
1 2 3 4 5 6 7
| import { computed } from 'vue' provide() { return { username: computed(() => this.username) } },
|
同时取数据也要.value 形式
# vuex 更高效的数据维护
Vue3.x 中的 axios 全局配置
在 main.js 中通过 app.config.globalProperties 全局挂载 axios
1 2 3 4 5 6 7 8 9 10 11 12
| 导入 import axios from 'axios' axios.default.baseUrl='http://127.0.0.1' const app=createApp(App) app.config.globalProperties.$http=axios app.mount('#app')
|
使用
1
| this.$http.get('/post',参数)
|