项目创建--vue-cli
vue create 项目名
npm run dev
npm run build
项目创建--vite
npm init vite@latest
npm install
npm run dev
vue3
1.template标签支持多根点
2.script标签成员:name,data(){return{}},methods
3.配置less语法的支持
npm i less -D
组件注册
//全局注册 main.js
import { createApp } from 'vue'
import './style.css'
// 导入挂载组件
import App from './App.vue'
// 导入全局组件
import 引入组件名 from ''
// 挂载渲染区域
const app = createApp(App)
// 组件全局挂载
app.component('全局注册之后的组件名',引入组件名)
app.mount('#app')
//局部注册 对应vue组件中
export default ={
components:{
'局部注册之后的组件名',引入组件名
}
}
scoped :deep(.title)
props自定义属性
方便父组件向子组件传递数据
props:['title','author']
props:{ // Sting Array Object Date Function Symbol 符号类型
title:Number,
author:Boolean
sex:[String,Number]
}
props:{
title:{
type:Number,
required:true,
default:100
}
author:{
validator(value){
return ['data1','data2'].indexof(value) !== -1 // true 通过 false 失败
}
}
}
可以通过v-bind 动态绑定数据 v-bind: title=""
:class
:class=" isItalic?'italic':'' "
:class="[:class=" isItalic?'italic':'' ",:class=" isItalic?'italic':'' "]"
<h3 :class="controlObj"></h3>
<button @click="controlObj.isDelete =! controlObj.isDelete"></button>
:style
<h3 :style="{color:active,fontSize:size+'px'}"></h3>
计算属性
computed:{
plus(){
return count*2
}
}
自定义事件
export default {
emits:['change']
methods:{
onBtnClick(){
this.$emit('change')
}
}
}
子向父同步数据
props:['number']
emits:['update:number']
add(){
this.$emit('update:number',this.number+1)
}
watch:{
数据名:{ 函数名(){},immediate:true,deep} //对象类型监听器,immediate true页面进入调用,false页面进入不调用 deep 数据内部任何数据改变都会触发
'父属性.属性名'(){}
数据名(newVal,oldVal){} //新旧值得获得
} //侦听器 书写同methods 方法名和数据名相同
eventBus
//bus
const bus = mitt()
export default bus
//
import bus from ''
bus.emit('',data)
bus.on('',()=>{})
后代共享数据
// 祖辈组件
export default {
provide(){
return {
color:this.color
}
}
}
//子孙组件
export default {
inject:['color']
}
color.value
生命周期函数
生命周期:一个组件由创建--》运行--》销毁
生命周期函数:vue框架提供的内置函数,自动按次序执行,生命周期函数强调的是时间点。
1.组件创建阶段:new vue() --> beforeCreate[创建前] --> created[已创建] --> beforeMount[未渲染] --> mounted[已渲染]
2.组件运行阶段:beforeUpdate[更新之前] --> updated[更新]
3.组件销毁阶段:beforeDestroy[销毁前] --> destroyed[销毁]
1.beforeCreate:data props methods 都不可用,只初始化了事件和生命周期函数
2.created: data props methods 都已经创建好,但是组件的dom结构尚未渲染,发起ajax请求,准备数据
3.beforeMount:浏览器结构存在于内存,未渲染到页面上,不能进行dom元素
4.mounted:页面dom结构存在,可以进行dom操作
5.beforeUpdate:将要根据最新数据进行重新的页面渲染时
6.updated:已经根据改变的数据进行了dom元素渲染
7.beforeDestroy:组件还能运行,销毁之前
8.destroyed:组件已经销毁,dom结构完全移除
数据共享
数据共享:
1.父向子组件共享数据需要使用自定义属性 props
2.子向父组件共享数据需要使用自定义事件
子组件定义事件:
方法(){
//触发自定义事件
this.$emit('事件名',this.数据)
}
父组件接受数据:
监听事件名方法(val){
this.接受的数据=val
}
3.兄弟组件之间的数据共享的方案是EventBus
兄弟a:
import bus from './eventBus.js'
定义发送数据方法(){
bus.$emit('share',this.mesg)
}
中间文件:eventBus.js
import Vue from 'Vue'
向外共享vue实例
export default new Vue()
兄弟b:
接受发在created生命周期函数中接受
import bus from './eventBus.js'
定义接受数据方法(){
bus.$on('share',val =>{
this.接受变量= val
})
}
ref dom操作
ref的引用dom元素
在每一个vue的实例中都有一个$refs的对象,凡是有ref属性的dom元素都会在其中,ref中的名不能相同
this.$nextTick(callback)
使回调函数在页面渲染完毕后,在进行执行
this.$nextTick(()=>{
this.$refs.xxx.xxx=xxx
})
动态组件和插槽
动态组件 插槽 自定义指令
动态组件
动态切换组件的显示和隐藏 inactive 组件被缓存,未显示
通过内置组件<component></component>
<component is="组件名"></component> component 相当于一个占位符
组件切换时,组件会销毁,
通过内置组件<keep-alive></keep-alive>保持隐藏组件不被销毁
<keep-alive>
<component is="组件名"></component> component 相当于一个占位符
</keep-alive>
组件切换时,组件不被销毁
对应的生命周期
deactivated:被缓存的
activated:被激活的
keep-alive的include属性可以指定哪几个组件可以缓存
<keep-alive :include="组件名称,组件名称">
<component is="组件名"></component> component 相当于一个占位符
</keep-alive>
keep-alive的exclude属性可以指定哪几个组件不被缓存 但是两个属性不能同时使用
组件名称
如果组件声明时没有注册名称,则组件名称默认为 注册时的名称
export default{
name:"xxx" //设定组件名称
}
插槽
<slot name="default"></slot>插槽标签
封装组件时,作为占位符存在
vue官方规定:每一个插槽slot插槽都必须有一个name名称
使用格式:
<组件>
<template v-slot:插槽的name名称="obj"> obj接受子标签传递的内容,返回的内容时键值对的对象
<插入的标签></插入的标签>
</template>
</组件>
template 只提供包裹的作用,不会出现在dom结构中
v-slot 指令的简写为 #
插槽的默认内容
<slot name="default" msg="子传父的信息">这是slot的默认内容</slot>
具名插槽
带有name的插槽
作用域插槽
带有name的插槽,并且传递数据
自定义指令
私有自定义指令
directives:{
指令名:{
//只有第一次绑定时,会产生效果
bind(el,obj--binding){ //el固定写法,el指当前绑定的dom对象,官方推荐binding.value 获得传入值 binding.expression 用户在等号后的表达式
el.style.xxx = xxx
},
//每次dom更新时被调用,但是第一次渲染没有效果
update(el,obj--binding){ //el固定写法,el指当前绑定的dom对象,官方推荐binding.value 获得传入值 binding.expression 用户在等号后的表达式
el.style.xxx = xxx
}
}
}
使用格式:<p v-指令名></p>
如果bind和update函数内的逻辑结构相同,则可简写为
指令名(el,obj--binding){ //el固定写法,el指当前绑定的dom对象,官方推荐binding.value 获得传入值 binding.expression 用户在等号后的表达式
el.style.xxx = xxx
},
全局自定义指令
Vue.directive('指令名',{
//只有第一次绑定时,会产生效果
bind(el,obj--binding){ //el固定写法,el指当前绑定的dom对象,官方推荐binding.value 获得传入值 binding.expression 用户在等号后的表达式
el.style.xxx = xxx
},
//每次dom更新时被调用,但是第一次渲染没有效果
update(el,obj--binding){ //el固定写法,el指当前绑定的dom对象,官方推荐binding.value 获得传入值 binding.expression 用户在等号后的表达式
el.style.xxx = xxx
}
})
Vue.directive('指令名',(el,binding)=>{
el.style.xxx = xxx
})
vue-router
vue-router是vue.js官方给出的路由解决方案。可以轻松的管理SPA(单页面程序)项目中组建的切换
vue-router的官方文档:https://router.vuejs.org/zh/
安装和配置
1.安装vue-router包
npm i vue-router@3.5.2 -S
2.创建路由模块
在src源代码目录下,新建router/index.js路由模块
路由模块的初始代码:
//导入vue和vue-router包
import Vue from 'vue'
import vueRouter from 'vue-router'
//调用Vue.use()函数,把vueRouter安装为Vue的插件
Vue.use(VueRouter)
//创建路由实例
const router = new VueRouter()
//向外共享路由实例
export default router
3.导入并挂载路由模块
new Vue({
render:h => h(APP),
// render:function(h){
// return h(APP);
// }
router: 路由实例对象
})
4.声明路由链接和占位符
占位符
<router-view></router-view>
声明路由链接:src/router/index.js
const router = new VueRouter({
//routes是一个数组,作用:定义“hash地址”与“组件”之间的对应关系
routes:[
{path:'/home', component:组件名},
{path:'/body', component:组件名}
]
})
<router-link to="/home"></router-link>可以代替A链接,不用向a标签那样必须加上#
路由重定向
用户访问a地址时,强制跳转到c地址
const router = new VueRouter({
//routes是一个数组,作用:定义“hash地址”与“组件”之间的对应关系
routes:[
{path:'/',redirect:'/home'},
{path:'/home', component:组件名},
{path:'/body', component:组件名}
]
})
嵌套路由
通过路由实现组件的嵌套---路由里面的路由
子路由规则的声明
routes:[
{path:'/home', component:组件名},
{path:'/body', component:组件名},
{path:'/about', component:组件名,children:[{path:'table1',component:组件名},{path:'table2',component:组件名}]}
] //子路由官方规定,路径不要加/
默认子路由:如果子路由的path路径中有一个path为空,此子路由为默认子路由
动态路由匹配
代码格式
{path:'/movie/:id',component:Movie}
获得动态路由的id值
方法一:
对应组件:this.$route.params.id
方法二:
{path:'/movie/:id',component:Movie,props=true}
组件中
props:['id']
查询参数:?name=mike&age=23
this.$route.query.name
fullPath:完整的接口
this.$route.fullPath /movie/2?name=mike&age=23
path
this.$route.path /movie/2
声明式导航,编程式导航
声明式导航:通过a标签,或router-link
编程式导航:通过调用API方式实现导航的方式,location.href跳转到新页面的方式
v-router:编程是导航api
this.$router.push('hash地址')
跳转到指定的hash地址,增加一条历史记录
this.$router.replace('hash地址')
跳转到指定的hash地址,不增加历史记录
this.$router.go(数值n)
在浏览历史当中前进或是后退
负值:后退 后退超限,会原地不动
正值:前进
this.$router.back() 行内this得省略
后退一个页面
this.$router.forward()
前进一个页面
导航守卫
全局前置守卫
const router = new VueRouter({....})
router.beforeEach(function(to,from,next){
// to 是将要访问的路由的信息对象
// from 是将要离开的路由访问对象
//next 是一个函数,调用next表示放行,允许这次路由导航
if(to.path == '/main'){
const token = localStorage.getItem('token') //localStorage.removeItem('token') localStorage.setItem('token','Bearer xxx')
if(token){
next()
}else{
next('/login')
}
}else{
next()
}
}) //回调函数 每次发生路由导航跳转的时候,自动触发
next的三种调用方式
用户有访问权限,直接放行:next()
用户没有访问权限,强制跳转登录页:next('/login')
用户没有访问权限,强制停在当前页面:next(false)