vue项目
vue项目中src
目录的构成
assets
: 存放项目中用到的静态资源文件,例如css,图片资源等components
: 存放我们封装的、可复用的组件main.js
: 项目的入口文件,整个项目的运行要先执行main.jsApp.vue
: 项目的根组件
vue项目的运行流程
在工程化项目中,vue要做的事情: 通过main.js
把App.vue
渲染到index.html的指定区域中。
App.vue:用来编写待渲染的模板结构
index.html中需要预留一个el
区域
main.js把App.vue渲染到index.html所预留的区域中
1.vue组件
组件化开发
指的是根据封装
的思想,把页面上可复用的UI结构封装为组件,从而方便项目的开发和维护。
vue中的组件化开发
- vue是一个支持组件化开发的框架
- vue中规定: 组件的后缀名是
.vue
vue组件的三大组成部分
template
: 组件的模板结构script
: 组件的js行为style
: 组件的样式
使用组件的三个步骤
1.使用import
语法导入
需要的组件
2.使用components
节点注册
组件
3.以标签
的形式使用
注册好的组件
- 通过components注册的是
私有组件
1.注册全局组件
某个组件要频繁的使用到,定义为全局组件
。
main.js
->导入需要注册的全局组件
->Vue.components('注册名称',组件)
// 导入需要注册的全局组件
import Global from '@/components/Global.vue'
// 注册全局组件
Vue.component('Myglobal', Global)
2.组件的props
props
是组件的自定义属性
,在封装通用组件的时候,合理的使用props可以极大的提高组件的复用性。
声明init自定义属性:
default
: default定义属性的默认值type
: type来定义属性值的类型required
: 定义属性是必填项
3.组件之间的样式冲突问题
默认情况下,写在.vue组件中的样式会全局生效,因此很容易产生多个组件之间样式冲突的问题。
解决组件中的样式冲突:
- 给当前组件的
style
添加scoped
属性 - vue在底层生成这个组件的时候,自动为每个dom元素都生成
data-v-xxx
属性 - 一个组件中都同用一个data-v-xxx属性
4./deep/的使用
在父组件中要修改子组件的样式,可以用/deep/
。
- 使用/deep/后,子组件dom元素就有了与父组件相同的
data-v-xxx属性
- 当使用第三方组件库的时候,如果有修改第三方组件默认样式的需求,需要用到/deep/
5.组件的生命周期函数
(1)组件创建阶段
beforeCreate()
- 组件的props/data/methods尚未被创建,都处于不可用的状态。
created()
- 组件的props/data/methods
已创建
好,都处于可用
状态 - 经常在这个阶段,调用methods中的方法,请求服务器数据,并且把请求到的数据转存到data中,供template模板渲染的时候使用
beforeMount()
- 将要把内存中编译好的html结构渲染到浏览器中
mounted()
- 已经把内存中的html结构,成功的渲染到浏览器中,此时浏览器中包含有组件的dom结构。
- 这个阶段中可以
第一次操作DOM
(2)组件运行阶段
beforeUpdate()
- 将要根据变化过后的最新数据,重新渲染组件的模板结构
- 此时data里的数据是最新的,但UI结构的内容是旧的
updated()
- 根据最新的数据,完成了dom结构的重新渲染,此时data数据和dom结构同步
- 此时可以操作
最新的dom
(3)组件销毁阶段
beforeDestroy()
- 将要销毁此组件,此时尚未销毁,组件还处于正常工作状态
destroyed()
- 组件已销毁,此时组件在浏览器中对应的dom结构已经被完全移除
组件创建阶段和销毁阶段自始至终都是执行一次,而执行阶段可以执行0~n次。
6.组件之间的数据共享
(1)父组件向子组件共享数据
子组件中声明props
接收父组件传过来的值:
- 需要使用自定义属性
父组件中定义数据,并在new子组件的过程中绑定传值
:
(2)子组件向父组件共享数据
子组件通过$.emit('事件名称',数据)
触发自定义事件:
- 需要使用自定义事件
父组件绑定
自定义事件,通过事件处理函数,接收传过来的值:
(3)兄弟组件之间的数据共享
创建eventBus.js
模块,并向外共享一个Vue实例:
在数据发送方,通过bus.$emit('事件名称',发送的数据)
方法触发
自定义事件:
在数据接收方,通过bus.$on('事件名称',事件处理函数)
方法绑定
自定义事件:
- 需要使用到eventBus
7.ref引用
ref
辅助我们在不需要调用domAPI(不依赖JQeury)的情况下,获取DOM元素或组件的引用。
(1)ref引用dom元素
在模板中的元素上,添加ref=""
通过this.$refs.dom元素.样式
方式修改dom元素
- ref的属性名不能重复,否则会冲突
- 每个vue的组件实例上都包含有一个
$refs对象
,里面存储着对应的DOM元素或组件的引用(默认为空)。
(2)ref引用组件实例
在对应的组件上,添加ref属性
通过this.$refs.组件实例.data
/methods
- 这样就能访问到LeftSon组件中的methods或data了
扩展:
this.$nextTick(cb)
等组件的DOM更新完毕后,再执行cb回调函数,从而保证cb回调函数内可以操作到最新的DOM元素。
- 使用
this.$nextTick(cb)
可以延迟cb
的调用,直到dom根据最新的数据重新渲染完毕后,才去执行
8.动态组件
vue提供了一个内置的<component>
组件,专门用来实现动态组件的渲染,<component>
相当于组件的占位符
。
(1)创建动态组件
- 在
<component>
中定义的动态组件,切换组件时会重新创建
或销毁
(2)keep-alive组件缓存
<keep-alive>
可以把内部的组件进行缓存
。
- 当切换其他组件时,组件缓存。当再次切换回来时,组件激活,并不会重新被创建。
当组件进行缓存时,检查可以看到:
(3)keep-alive的生命周期函数
<keep-alive>
有两个生命周期函数,分别是: activated(),deactivated()。
activated()
:表示组件被激活(第一次创建组件的时候也会触发)deactivated()
:表示组件被缓存
(4)keep-alive的include属性&exclude属性
include
: 指定需要被缓存的组件(多个组件之间用,号分隔)exclude
: 指定不需要被缓存的组件
2.插槽
插槽
(slot
)是vue为组件的封装者提供的功能,开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。
1.插槽的基本使用
封装的组件中声明一个插槽区域
使用v-slot
指令把内容填充到指定的插槽中
v-slot:
可以简写为#
2.具名插槽
插槽带有name
名称也叫具名插槽
。
3.作用域插槽
封装组件时,预留的插槽中指定了数据项
的属性,则称为作用域插槽
。
往插槽填充内容时,要使用到数据项,则用插槽名称=
来接收
- 默认情况下,若预留插槽中没有指定属性,得到的是空对象
{}
- 可以使用
对象解构
的方式来接收插槽的属性
3.自定义指令
1.私有自定义指令
只在当前组件中生效的指令。
在每个vue组件中,可以在directives
节点下,声明私有自定义指令
bind
:只能调用一次。即指定第一次绑定到元素时调用,当DOM更新时bind函数不会触发update
:在每次DOM更新时调用
简写形式:
使用自定义指令
2.全局自定义指令
全局共享的自定义指令,其他组件都能用。
在main.js
中声明全局自定义指令
Vue.directive('指令名称',function(el,binding){})
4.vue路由
前端路由就是Hash地址
与组件
之间的对应关系
。
前端路由的工作方式
1.用户点击了上面的路由链接
2.导致url地址栏的hash值发生了变化
3.前端路由监听到了hash地址的变化
4.前端路由把当前hash地址对应的组件渲染到浏览器中
- 前端路由底层原理是监听了
onhashchange
事件,当哈希地址改变时,把当前哈希地址对应的组件渲染到页面中。
1.vue-router的基本使用
vue-router
是vue.js官方给出的路由解决方案。它只能使用在vue项目中,能够轻松的管理SPA项目中组件的切换。
官网: https://router.vuejs.org/zh/
(1)安装vue-router
npm i vue-router@3.5.2 -S
(2)创建路由模块
(3)导入并挂载路由模块
main.js中导入并挂载
(4)声明路由链接和占位符
(5)定义hash地址与组件之间的对应关系
2.路由的重定向
通过路由规则的redirect
属性,指定一个新的路由地址,就可以设置路由的重定向
。
3.嵌套路由
通过路由实现组件的嵌套展示,叫做嵌套路由
。
- 通过
children
属性声明子路由规则 - 点击父级链接显示模板内容,模板内容中又有子级路由链接,点击子级路由链接显示子级模板内容。
展示父路由的同时也展示子路由
(1)可以用重定向
(2)可以用默认子路由
- children数组中,某个路由规则的
path
值为空
时,则为默认的子路由。
4.动态路由
把Hash地址中可变的部分
定义为参数项
,从而提高路由规则的复用性。
- 在路由规则中使用英文的冒号
:
来定义路由的参数项。
拿到参数项匹配的值
(1)传统方式
this.$route.params
(2)为路由规则开启props传参
props:true
组件中声明props,拿到动态参数的值
扩展
在hash地址中,/
后面的参数项,是路径参数
。
- 在路由参数对象中,使用
this.$route.params
来访问路径参数
在hash地址中,?
后面的参数项,是查询参数
。
- 在路由对象中,使用
this.$route.query
来访问查询参数
在this.$route
中,path
只是路径部分,fullpath
是完整的路径。
5.路由导航
(1)声明式导航
在浏览器中,点击链接
实现的导航方式,叫声明式导航
,如:网页中点击普通的a链接,vue项目中点击<router-link>
都属于声明式导航。
(2)编程式导航
在浏览器中,调用API
方法实现的导航方式,叫编程式导航
,如:普通网页中调用location.href
跳转到新页面的方式,属于编程式导航。
(3)vue-router中的编程式导航
vue-router提供了许多编程式导航的API,如:$router.push()
,$router.replace()
,$router.go()
。
this.$router.push('hash地址')
: 表示跳转到指定hash地址,并增加一条历史记录
this.$router.replace('hash地址')
: 表示跳转到指定hash地址,并替换掉当前的历史记录
this.$router.go(数值n)
: 表示在浏览历史中前进或后退n页$router.go
的简化:$router.forward()
,$router.back()
6.导航守卫
导航守卫可以控制路由的访问权限
。
(1)全局前置守卫
每次发生路由跳转时,都会触发全局前置守卫。因此,在全局前置守卫中,我们可以对每个路由进行访问权限控制。
声明全局前置守卫
next函数的3种调用方式: next(),next(‘/路径’),next(false)。
next()
: 当前用户拥有后台主页的访问权限,直接放行next('/login')
: 当前用户没有后台主页的访问权限,强制跳转到登录页面next(false)
: 当前用户没有后台主页的访问权限,不允许跳转到后台主页,停留在当前页面