概述:Vue是一款用于构建用户界面的 JavaScript 框架。
它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。
渐进式:vue可以自底向上逐层的应用,无论是简单还是复杂的界面,Vue 都可以胜任。
简单应用:只需一个轻量小的核心库
复杂应用:可以引入各式各样的vue插件
渐进式就是按需逐渐集成功能
Vue的特点:
采用组件化模式,提高代码复用率、且让代码更好维护。
目标:更少的时间,干更多的活,开发网站速度快
原生js:操纵dom
vue:操纵数据
声明式开发:无需直接操作DOM
组件式开发:将页面拆分成很多个小组件,重复的直接复用即可,更方便管理
1、M:模型(Model):对应data中的数据
2、V:视图(View):模板
3、VM:视图模型(ViewModel):Vue实例对象//桥梁
1、调试插件:vue.js devtools//谷歌商店下载
2、代码高亮和提示插件:Vue Language Features (Volar)和VueHelper
绝大多数和vue2相同
1、Vue2:
语法一:
new Vue({
el:'#app',//标签,写法一
data:{
name:'张三'//数据,对象式
}
})
语法二:
const v = new Vue({
data(){ === data:function(){ //数据,函数式
return {
name:'张三'//数据,函数式
}
})
v.$mount('#app')//标签,写法二,使用的是原型对象上的方法,更灵活,比如定时几秒后再绑定
2、Vue3:
Vue.createApp({ // 当前应用实例的选项
data () { // 书写形式为函数,表示vue实例中需要使用的 数据的变量,必须含有返回值,返回值为对象
return {
msg: 'hi world',
count: 10
}
}
}).mount('#app')
3、Vue.config.productionTip = false//阻止 vue在启动时生成生产提示
1、插值语法:{{}}//不支持null和undefined
例如:<div>{{括号里可以放js表达式}}</div>
let num = 'hello';
<div>{{num.split('').reverse().join('')}}</div>
2、指令语法:
用于解析标签(标签属性、标签体内容...)
例如:v-bind:href="xxx"或简写为 :href="xxx",xxx要写js表达式
v-html 和v-text:都写在标签里当做属性
v-html:识别标签//存在安全性问题,容易导致xss攻击
不要将v-html用在用户提交的内容上
v-text:不识别标签
vue2中使用v-html和v-text会覆盖掉原标签里的内容
vue3中使用v-html和v-text,标签里有内容的话会警告
单向数据绑定://只能从data流向页面
语法:v-bind:属性名 = "data"
v-bind:属性名 = "常量"
v-bind:src="url"
简写::属性名="data中的变量"
双向数据绑定://不仅可以从data流向页面,也可以从页面流向data
语法:v-model//收集的是value的值,只能用于有value值的标签,比如input等
v-model绑定在多选上时,根据类型传值,非数组则为布尔,数组则为选中的
v-model绑定在下拉菜单上时,显示哪个,值就是哪个
1、语法:
v-on:事件类型="少量的js代码(要求代码是赋值语法)"
v-on:事件类型="函数名"
v-on:事件类型="函数名(参数)"
2、简写:
@事件类型="少量的js代码(要求代码是赋值语法)"
@事件类型="函数名"
@事件类型="函数名(参数)"
3、事件对象如何获取
如阻止事件的默认行为:e.preventDefault()
1)调用时不传参数时,默认就在第一个形参
2)如果传递参数了,需要在实参处写上$event,然后形参处接收
例如:@事件类型="函数名($event,66)"
4、简化版:
@事件类型.prevent = "事件处理函数"//阻止事件默认行为
@事件类型.stop = "事件处理函数"//阻止冒泡
@事件类型.stop.prevent = "事件处理函数"//阻止冒泡和默认行为
特殊的事件如keyup事件
@keyup.enter = "事件处理函数"//抬起并按下了回车,才会触发
@keyup.ctrl.enter = "事件处理函数"
......
1、v-if:
原理:使用js中创建和删除标签//切换一次耗一次性能
2、v-show:
原理:使用js中的display的block和none来控制//初始时消耗一次
3、安全性:v-if高于v-show
4、支持写在template标签上//辅助标签,不会显示出来
1.v-if支持
2.v-show不支持
1、语法:v-for="item in 数字"//想让谁出现多次,就把v-for写在谁神身上
例如:<span v-for="(item,index) in 10" :key="index"></span>
//key后要写唯一的东西,例如索引等
2、遍历数组:v-for = "(item,index) in data中的数组" :key="唯一的"
//item则是数组中每一个值
3、遍历对象:v-for = "(value,key) in data中的对象" :key="唯一的"
//value则是对象中每一个值
//v-for的默认行为会尝试原地修改元素而不是重新创建
vue3中,v-for和v-if的优先级谁更高//v-if优先级高
vue2中,v-for和v-if的优先级谁更高//v-for优先级高
//如果v-for优先级高,这就意味着v-if将重复的运行于每一个v-for循环中
//注意:v-if和v-for尽量不要写在一个标签上,将判断写在template标签上,循环写在里面的标签
<body>
<div id="app">
<table border="1">
<thead>
<tr>
<td>商品名称</td>
<td>商品单价</td>
<td>商品数量</td>
<td>商品小计</td>
<td>商品操作</td>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in list" :key="item.index">
<td>{{item.product}}</td>
<td>{{item.price}}</td>
<td>
<button @click="jianNum(item.id)">-</button>
<span>{{item.num}}</span>
<button @click="jiaNum(item.id)">+</button>
</td>
<td>{{item.num*item.price}}</td>
<td><button @click="remove(item.id)">删除</button></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5">
<span>总数:{{list.reduce((sum,item)=>sum+=item.num,0)}}</span>
<span>总价:{{list.reduce((sum,item)=>sum+=item.num*item.price,0)}}</span>
</td>
</tr>
</tfoot>
</table>
</div>
</body>
</html>
<script src="lib/vue.global.js"></script>
<script>
Vue.createApp({
data() {
return {
list: [
{ id: 1, product: "小米手机", price: 10, num: 1 },
{ id: 2, product: "华为手机", price: 60, num: 1 },
{ id: 3, product: "红米手机", price: 30, num: 1 },
{ id: 4, product: "锤子手机", price: 30, num: 1 },
{ id: 5, product: "小灵通手机", price: 10, num: 1 }
]
}
},
methods: {
jiaNum(id) {
this.list.find(item => item.id == id).num++;
},
jianNum(id) {
let good = this.list.find(item => item.id == id);
good.num = good.num <= 1 ? 1 : --good.num;
},
remove(id) {
this.list = this.list.filter(item => item.id != id);
}
}
}).mount('#app')
</script>
1、概念:模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。依赖其他属性计算而来的属性,可以写到computed选项中,写起来像方法,使用起来是属性。
2、计算属性 vs 方法
1)使用的时候,方法需要带() 计算属性不需要带()
2)计算属性值会基于其响应式依赖被缓存。当依赖项不发生,直接从缓存中取,当依赖项发生变化,会重新调用一次
3、语法://计算属性的名字不可以和data中变量名相同
语法一://这种写法值不可修改,只读
computed: {
计算属性的名字:function(){
return ;
}
}
语法二://这种写法值可读可写
computed: {
计算属性的名字: {
// 获取的语法
get() {
return;
},
set(val){
}
}
}
1、概念:侦听data中数据的变化
2、语法:
语法一://侦听的直接是基本类型属性
watch:{
"哪个data":function(newval,oldval){}
}
语法二://侦听对象
watch:{
"侦听哪个对象":{
deep:true,//深度侦听
immediate:true,//立即侦听,页面打开立即侦听
handler(newval,oldval){//newval变化后,oldval变化前
newval: 改变后的对象的值,对象中所有的属性都在newval包含
}
}
}
语法三://手动开启侦听
this.uwatch = this.$watch('侦听的属性',(newval=>{}))//开启侦听
this.uwatch();//结束侦听
3、watch 默认是懒执行的:仅当数据源变化时,才会执行回调。
可以用一个对象来声明侦听器,这个对象有 handler 方法和 immediate: true 选项,这样便能强制回调函数立即执行
1、基本绑定样式:
例:<p :class="active"> 白日依山尽 </p>
2、对象的方式:
例:<p :class="{'常量型类名':true,'常量型类型':true}"></p>
//键作为类名,值为布尔,为true则键作为类名加在p上
3、数组的方式:
例:<p :class="['常量型类名',变量型类名]"></p>
//将[常量型类名]和[变量型类名]作为类名加在p上
4、style的方式:
例:<p :style="{属性名:'属性值(常量要带引号/变量)',fontSize:'28px'}"></p>
//常量带-的要用驼峰
const vm = new Vue({
el:'#app',
data:{}
})
1、data和vm关系:
vm是data的代理对象
Object.defineProperty 通过代理对象vm,能够捕获到对象源data的修改和获取操作,无法捕获到添加和删除
1、Object.defineProperty:
限制一:只能捕获到对象的获取和设置,不能捕获对源对象的添加和删除
限制二:js的限制,无法捕获到数组中某个值的变化,数组的方法操作也无法捕获
//vue中重写了push、pop、shift、unshift、splice、reverse、sort能改变原数组的方法,让这些方法可以触发set方法,从而触发watch侦听,从而更新页面
不改变原数组的方法,可以通过赋值,覆盖原数组的方式,触发自动更新
通过数组下标修改数据不会触发自动更新,需要强制更新
vue里还提供了,强制更新数据到页面的方法:
this.$forceUpdate()
概念:处理一些数据的//例如时间戳的处理
{{过滤前 | 过滤后}}//标签里
data:{
过滤前:value
}
语法一:
filters:{//过滤器
过滤后:function(val){
console.log(val)//处理
}
}
语法二:
filters:{//过滤器
过滤后:function(val,形参){
console.log(val+形参)//处理
}
}
概念:上面学习的都是内置指令
1、v-cloak指令:
是一个特殊属性,写在标签上,配合css里设置[v-cloak]{display:"none"}
可以防止页面出现,未解析完毕的内容,如{{xxx}}...
2、v-once指令:
v-once所在标签在初次渲染完毕后,就会视为静态内容,以后数据改变,不会引起v-once所在结构的更新,用于优化性能。
3、v-pre指令:
让vue跳过其所在标签,不对其进行解析,优化,加快编译
1、创建语法:
//app.component("组件名字",{组件中的内容})
//定义了一个全局的组件
app.component("myHeader", {
template: ``,
data() {
return {
msg: 'header子组件'
}
},
methods: {}
})
//定义了一个局部的组件
app.component("myHeader", {
template: ``,
data() {
return {
msg: 'header子组件'
}
},
components:{//这里写的就是局部组件
}
methods: {}
})
//vue2定义组件
const 组件名 = Vue.extend({})
简写语法:const 组件名 = {组件内容}
2、使用语法://驼峰转换为小写,-连接
<my-header></my-header>
1、组件本质是一个名为VueComponent的构造函数,是由Vue.extend生成的
2、是需要写' ',Vue解析时会帮我们创建school组件的实例对象,即调用new VueComponent(options)
3、每次调用Vue.extend时返回的都是一个全新的VueComponent
4、this指向:
1)组件配置中:
data、methods、watch、computed中的函数,this指向为VueComponent实例对象
2)new Vue(options)配置中:
data、methods、watch、computed中的函数,this指向为Vue实例对象
5、VueComponent组件实例对象
一、props配置项:
1、功能:让组件接收外部传过来的数据//组件通信之父传子
2、传递数据:在父组件里给子组件加动态属性(通过v-bind绑定属性方式),属性值为父组件的数据
<Demo :name='xxx'/>
3、接收数据:
方式一:(只接收):props:['name']
方式二:(限制类型):props:{name:String}
方式三:(限制类型、限制必要性、指定默认值):
props:{
name:{
type:String,//类型
required:true, //必要性
default:'张三'//默认值
}
}
4、props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,必须要修改时,可以复制一份新的,修改新的数据
二、组件通信之字传父:
1.在父组件里给子组件的标签上设置一个自定义事件,事件处理函数就是写在父组件的方法
2.在子组件中使用emits接受父组件传递过来的事件名
3.在子组件内合适的时机(点击按钮等),触发自定义事件执行,并传参给父组件
1、搭建:vue3
1)安装node(16以上的版本)
2)npm init vue@latest//下载vue说明书
Project name //文件名
默认no直接回车...
3)cd 文件名 //进入到创建的文件
4)npm i //下载说明书里的第三方模块
5)npm run dev /vue项目
6)删除vue里的无用文件
2、各个文件作用:
public
favicon.ico:页签图标
src
assets://静态资源
components://用于存放组件的文件夹
App.vue:汇总所有组件
main.js://整个项目的入口文件
import { createApp } from 'vue' //解析出vue实例
import App from './App.vue' //导入app组件,它是所有组件的父组件
createApp(App).mount('#app') //创建vue实例对象---vm
index.html:主页面
.gitignore://git忽略文件
babel.config.js://babel控制文件,用于将es6转为es5
package-lock.json://包版本控制文件
package.json: //说明书
README.md://文档
3、使用
1)在app.vue书写核心组件
2)components里书写其他组件
组件里必须包含
<script></script>
<template></template>
<style scoped></style>
//scoped让样式在局部生效,防止冲突
3)子组件功能书写完毕后,将组件导入到核心组件里,拼为一个完整页面
4)终端输入 output.js //将vue脚手架默认配置整理成一个js文件
1、概念:父组件传递给子组件时,子组件没有接受父组件传递的属性,子组件最终会渲染成标签,同时传递的数据都绑定在这个标签上,数据可以通过$attrs.属性名来获取属性值
2、子组件使用props接收父组件传递的属性,则会渲染为标签,同时传递的数据没有绑定在这个标签上
父组件传递数据给子组件时,子组件没有使用emits接收父组件传递的事件,子组件中可以直接触发这个事件
不想接收透传的属性,可以将inheritAttrs
1、ref:获取标签,使用时用$refs
1)被用来给元素或子组件注册引用信息//代替id
2)应用在html标签上获取的是真实的dom元素,应用在组件标签上是组件实例对象
3)使用方式:
打标识:<h1 ref='xxx'>...</h1>
获取:this.$refs.xxx
2、$parent:触发父组件
在子组件中拿父组件的属性和方法
3、$root:触发根组件
在孙组件中拿根组件中的属性和方法
1、含义:又名(生命周期回调函数、生命周期函数、生命周期钩子,Vue,关键时刻帮我们调用的一些特殊名称的函数,具体时间做具体的事情,分为四个阶段,八个生命周期//this指向都为vm或组件实例对象
2、四个阶段:
1)创建阶段:
beforeCreate//创建实例前
created//创建完成
2)挂载阶段
beforeMount//挂载前(挂载到dom上)
mounted//挂载完成***
3)更新阶段(触发更新,数据变化,dom元素新增和删除)
beforeUpdate//更新前
updated//更新
4)销毁阶段
Vue2: beforeDestory//销毁前*** destoryed//销毁后
Vue3: beforeUnMount//销毁前*** unmounted//销毁后
3、常用的声明周期钩子:
1)mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
2)beforeUnMount:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
4、销毁Vue实例 //手动删除vm this.$destroy()
1)销毁后借助Vue开发者工具看不到任何信息
2)销毁后自定义事件会失效,但原生Dom事件依然有效
3)一般不会再beforeDestroy操作数据,因为即使操作数据了,也不会触发跟新流程了
1、兄弟组件传值:
vue2:先实例化一个公共的通信对象eventBus,其中一个组件通过$on监听事件,另外一个兄弟组件通过$emit去触发事件
2、跨组件传值:外层组件通过provide选项传值,内层组件通过inject传值
1、作用:自定义组件内容
2、 默认插槽:不需要起名<slot/>
具名插槽:需要起名<slot name=""/>
1、component动态组件
2、keep-alive:缓存组件,包裹在需要缓存的组件外部,被缓存的组件会保留在内存中,组件下次切换时只需要从内存中读取并显示出来即可
//include---指定需要缓存的组件列表(使用时必须给组件设置name)
//exclude---指定不需要缓存的组件列表
<keep-alive include="ChildA,ChildB" exclude="ChildC">
<component :is="组件"/>
</keep-alive>
3、与keep-alive搭配使用的两个钩子函数:
deactivated//进入缓存
activated//激活组件
transition:动画组件//Transition包裹的必须是一个单根的组件
<transition name="默认v" mode="出入顺序"><transition>
对象的选择器:vue3
.name名-enter-from: 入场动画开始前的状态
.name名-enter-active: 入场动画开始后的状态
.name名-leave-from: 离场动画开始前的状态
.name名-leave-active: 离场动画开始后的状态
mode:出入顺序
out-in:先出后入
in-out:先入后出
1、自定义指令:directives//用于封装自定义指令
//定义时不加v-,使用时要写加v-
2、局部指令:
directives:{
自定义指令名:{
//在绑定元素的父组件及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode) {
el:指令绑定到的元素。这可以用于直接操作 DOM。
}
}
}
//自定义指令中的this都是window
2、全局自定义指令//任何组件都可已使用
//简化形式
app.directive('指令名',(element,binding){
// 这会在 `mounted` 和 `updated` 时都调用
//element真实dom元素,binding本次绑定的信息
})
功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
定义插件:
myplugins
export default{
install(app){}
}
导入插件:import myplugins from '路径/myplugins'
使用插件:app.use(myplugins插件名)
1、功能:抽离多个组件的公共代码(选项),将抽离的代码放在单独的文件里,需要用时引入,避免代码冗余。 //单独文件(mixins)里能写在都是已有的选项
2、使用:mixins:[名],混入的公共代码会出现在选项内
$forceUpdate()//让组件强制更新
$nextTick()//可以让特定代码在组件的下次更新周期到后再执行
1、概念:单个页面,通过地址栏地址变化,跳转不同页面实现更新页面内容的技术
2、在vite构建的vue单页面应用中,需要借助vue-router库,实现路由功能
3、配置路由表:
单条路由的配置:
{path:'/login',component:Login}
嵌套路由:
{
path:'/index',//地址后写什么
component:Index//组件
children:[]//嵌套的路由必须跟在/index/后面
},
重定向:{path:'/',redirect:'/index'}
404:{path:'/:error(.*)',component:NotFound}
4、路由组件
<router-link to="用来跳转路由">//最终渲染成a标签
router-view//充当路由渲染出口
5、路由实例:
$router//路由管理对象,负责跳路由
$route//路由对象,负责存储路由信息
6、条路由的两种方式:
标签式导航:借助router-link渲染的a标签来跳转
编程式导航:借助$router的push,go方法来跳路由
7、条路由传参:
动态路由传参:
配置路由:{path:'/detail/:id',component:Detail}
传参:this.$router.push("/detail/"+参数)
接参:this.$route.params.id
固定路由传参:
传参:this.$router.push({path:"/detail/",query:{id}});
接参:this.$route.query.id
8、parmas和query的区别
parmas在地址栏不显示key,而query的key和value都显示,前者更安全;
parmas上线率先你会丢失,query不会;
语法不同
9、组件内---对某些组件进行路由跳转时生效
进入组件时//beforeRouteEnter
离开组件时//beforeRouteLeave
1、概念:为了减少页面加载时间,在需要的时候再调用对应的js文件。
用懒加载方式导入每个组件,每个组件都会单独生成一个js文件,当你实际访问哪个路由,对应的组件文件才会加载,否则不加载。
2、使用:var MyIndex = () => import('../views/MyIndex.vue');
1、概念:在到跳路由前、后做的一些操作//比如跳购物车页面判断下是否登录
2.语法:
router.beforeEach((to,from,next)=>{//全局前置守卫函数
to//去往哪里的路由对象,判断是否携带token,没带跳登录
from//来自哪里的路由对象
next('/login')//不写参数放行,写了就是强制跳该路由
})
//全局后置守卫函数
router.afterEach()
3、应用:
1)控制路由跳转
2)配合nprogress实现进度条的播放
import nProgress from 'nprogress'
import 'nprogress/nprogress.css'
nProgress.start();//开始播放进度条动画
nProgress.done();//停止播放进度条动画
1、移动端:vant UI
2、PC端:
element UI//vue2
element plus//vue3
1、概念:基于Promise的Http请求工具库,支持浏览器端和NodeJS端
2、下载axios插件、并对其进行封装
3、实例化一个axios对象,并在其上添加拦截器
var service = axios.create{//1.实例化axios
timeout: 毫秒, //超时时间
baseURL: '', //基准路径,比如写个/api,则以/api开头的可以省略/api
}
service.interceptors.request.use(//2.设置 请求 拦截器
//请求从本地发给服务器之前执行,一般用于添加请求头
(config)=>{return config;},
(error) => {return Promise.reject(error);} //请求发生错误时的处理
)
service.interceptors.response.use{//3.设置 响应 拦截器
(res)=>{return res;}, //请求从服务器发送回来时执行
//对请求发生错误时的处理,一般用于判断不同状态码做对应处理
(error) => {return Promise.reject(error);}
}
export default service;//导出
4、配置代理
1)概念:如果不做配置,默认发送的ajax请求,会发给vscode临时开启的服务器
server: {
proxy: {//代理
'/api': {//所有以/api开头的请求都会发送给目标服务器
target: '目标服务器地址', //目标服务器
changeOrigin: true,//开始跨域
}
}
}
5、发送请求,并将每一个接口封装成一个函数,并导出//便于统一管理
封装:
export function 名(参数 = {}) {
//get
return service.get('地址', { params: 参数 })
//post
return service.post('地址', 参数 );
}
使用:
import * as service from '路径';//集体导入到一个对象中
import { login } from '路径';//命名导入( 按需导入 )
service.名({ 参数}).then((res)=>{
console.log(res.data);//数据
})
1、打开浏览器在network里检查//文件名默认是请求地址最后一个单词
Headers:检查请求地址是否正确,请求头是否携带
Preview:检查返回的数据
2、
get请求参数格式:{params:{}}
post请求参数格式:{}
概念:Vuex是一个专为Vue.js应用程序开发的状态管理模式+库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
1、下载vuex插件,通过createStore实例创建一个store存储库
https://vuex.vuejs.org/zh/guide/#%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84-store
createStore({
state:{},//负责存储数据
getters:{},//定义计算方法(类似于计算属性,必须有返回值)
mutations:{},//定义同步方法(可以直接修改state中的数据)
actions:{},//定义异步方法(内部可以实行异步代码,但不能直接修改state中的数据)
modules:{},//模块化管理state中的数据
plugins:[]//配合其他插件管理state中的数据
})
2、使用:
this.$store.commit('同步方法名',参数)
this.$store.dispatch('异步方法名',参数)
this.$store.getters.计算方法名
3、其他插件
vuex-persistedstate//用于对state持久化存储
createLogger//日志打印插件,用于打印state数据
npm install vuex@next --save//安装vuex
npm install vuex-persistedstate//安装vuex-persistedstate
直接调用即可
plugins:[createPersistedState(),createLogger()]
1、模块化管理:vuex里state存放数据,而每一个数据对应着许多方法,如果存放的数据过多,那么就会导致有许多的方法写在一起,不方便管理,所有将一个数据拆分成一个模块,单独一个文件,用于管理该数据,再将所有模块统一管理。
2、模块的定义及管理
创建一个modules文件夹,用于存放模块
1)//模块的定义
export default {
namespaced:true, //让当前模块变成拥有自己独立作用域的私有模块
state:{},getters:{},mutations:{},actions:{}
}
2)//管理模块
import tasklist from './modules/tasklist'
import shopcart from './modules/shopcart'
//所有被管理模块都可以使用这里的数据,方法,插件
export default createStore({
state:{},getters:{},mutations:{},actions:{}
modules:{ //以模块化的方式管理state数据( 这里决定了每个模块的名字 )
tl:tasklist, //t1模块别名,tasklist模块名
sc:shopcart,
},
plugins:[ createLogger() ]
})
3)使用:
this.$store.state.模块名.xx
this.$store.getters['模块名/xx']
this.$store.commit['模块名/同步方法']
this.$store.dispatch['模块名/异步方法']
例:this.$store.dispatch( 'tl/request' );//调用了t1模块里面的异步方法:request
3、辅助函数
//mapActions() 将vuex中的异步方法映射到当前组件的methods中
//mapMutations() 将vuex中的同步方法映射到当前组件的methods中
//mapState() 将vuex中的数据映射到当前组件的computed中
//mapGetters() 将vuex中的计算方法映射到当前组件的computed中
1)用法:
import { mapActions, mapMutations, mapState,mapGetters } from 'vuex'
//直接写在计算属性(computed)里
...mapState('模块名', ['模块里的属性名'])
...mapGetters('模块名',['模块里的计算属性名','模块里的计算属性名'])
//直接写在方法(methods)里
...mapActions('模块名', ['模块里的异步方法名']),
...mapMutations('模块名', ['模块里的异步方法名', '模块里的异步方法名']),
映射后就可以直接通过this.方法(属性)名的方式直接调用
###1、组件化编码流程(通用)
1)实现静态组件:抽取组件,使用组件实现静态页面效果
2)展示动态数据:
2.1.数据的类型、名称是什么?
2.2.数据保存在哪个组件?
3)交互-从绑定事件监听开始
下载需要用到的库
创建并配置一级路由及相关组件,并验证,以此类推创建二级等
二次封装axios:实例化axios,并设置拦截器//添加请求头和对错误的处理等
使用axios的二次封装,进行对不同接口的封装,统一管理
可以使用await和async使请求按顺序发送
省略号:
overflow:hidden;
display:-webkit-box;
-webit-box-orient:vertical;
-webit-line-clamp:2;
1、setup声明周期函数(代替的是beforeCreate和created)
1)setup特点:
组件实例化时执行
this是undefined
定义的所有数据和方法都要return返回
2、vue3组合式组件通信
1)父向子传值:
父组件通过自定义属性传值,子组件props接收值,
也可以通过setup(props){}//setup第一个参数为props
2)子向父传值:
父绑定自定义事件,子通过emit触发事件并传值
setup(props,{emit})//setup第二个参数可以解构出emit
3)兄弟组件传值:
下载mitt插件,通过mitt实例化通信对象 export default mitt;
使用:导入通信对象,通过mitt.on提前绑定监听事件,mitt.emit触发事件
3、vue3组合式路由:
1)import {useRouter} from 'vue-router'
获取路由管理对象 var router = useRouter();
获取路由对象 var route = useRoute();
4、vue3组合式生命周期的变化:
将beforeCreate和created合并为了setup
其他声明周期前面都加了on,如onBeforeMount,且都要写在setup里
vue3组合式里没有this:
发请求等操作需要使用其他属性时,直接使用即可,不需要this
vue3组合式使用其他组件时,只需要导入,不需要注册,直接使用即可
5、定义响应式数据:
//两个api函数
1)reactive()//用于将引用类型数据转化为响应式数据(基本数据类型不能转化)
var count = reactive([0])
在js代码中获取reactive类型数据的原始值,直接使用即可
reactive解构后会丢失响应式,需要通过toRefs转化为响应式,在解构
2)ref()//可以将基本和引用类型数据转化为响应式数据
var count = ref(0)
在(js)代码中获取ref类型数据的原始值,必须借助.value属性
在模板中使用不需要带.value
3)toRefs//将reactive定义的响应式数据中的每个属性转化为Ref定义的响应式数据
6、定义方法、计算属性、watch
1)定义方法:var fn = ()=>{}
2)定义计算属性: var sum = computed(()=>{});
3)watch:
watch(count,(newVal,oldVal)=>{});//监听单个
watch([count,obj],(newVal,oldVal)=>{})//监听多个
watch(obj,(newVal,oldVal)=>{},{deep:true})//开启深度监听写法
1、pinia(与vuex)相同点:
1)都是状态管理库,都可以用于vue2、vue3
2)都支持响应式数据,可以在组件中轻松地访问和修改状态。
3)默认都没有持久化,需要手动开启
2、不同:
vuex使用的选项式的语法
pinia使用的组合式的语法
3、使用步骤:
npm install pinia
npm i pinia-plugin-persistedstate --save//持久化插件
在main.js中引入持久化插件
import {createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";//pinia持久化
const pinia = createPinia();
pinia.use( piniaPluginPersistedstate );
app.use(pinia)
//持久化开启
export const loginStore = defineStore('main',()=>{},persist:true)
自动导包插件:npm i unplugin-auto-import -D
并在vite.config.js配置
import AutoImport from 'unplugin-auto-import/vite'
plugins: [
vue(),
AutoImport({
imports:['vue','vue-router']//自动导入vue和vue-router相关api
})
],
@:代表了src
原引用文件的方式:import * as service from './api'
新引用文件的方式:import * as service from '@/api'//所有文件通用
1、setup语法糖写法:
<script setup>不用return</script>
1、router、pinia、element UI 及两个自动化插件并做配置
2、路由及路由表拆分、axios的封装(拦截器)、请求的统一归类并模块化
3、表单组件:
rules:设置验证规则
通过ref绑定from实例,submit(ref)接收,validate做校验
4、pinia数据存储的
1、配置:
npm install element-plus --save//下载
npm install -D unplugin-vue-components unplugin-auto-import//自动导入
//并在vite.config.ts做配置
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
2、icon图标
1)安装包:npm install @element-plus/icons-vue
2)main.ts里注册
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
1)父组件向子组件传值:父组件在子组件上,通过自定义属性传值,子组件内部通过props接收自定义属性,获取值
2)子组件向父组件传值:父组件需要在子组件身上绑定自定义事件,子组件内部通过$emit触发事件并传值
3)兄弟组件传值:
//只支持vue2
先实例化一个公共的通信对象eventBus,其中一个组件在挂载完毕mounted()生命周期函数里,通过$on提前绑定监听事件,另外一个兄弟组件在特定情况通过$emit去触发事件,并传值
4)跨组件传值:外层组件通过provide选项传值,内层组件通过inject选项接收值
5)v-model的特殊使用方式:
//vue3默认写法,update:modelValue必须这样写
方式一:父组件在子组件上,通过v-model="value"双向绑定,在子组件的input上使用
@input="$emit('update:modelValue', $event.target.value)
//父组件加:自定义的方式,update:自定义
方式二:父组件在子组件上,通过v-model:abc="value"双向绑定,在子组件的input上使用
@input="$emit('update:abc', $event.target.value)
//vue2默认写法:input
方式一:@input="$emit('input', $event.target.value)
//自定义方式
方式二:model{prop:'abc',event:'bbb'}
@input="$emit('bbb',$event.target.value)"
写在标签上,获取的是所在标签的dom节点
写在自定义组件上,获取的是所在组件的实例//可以调用其上的方法
1、component动态组件
2、keep-alive:缓存组件,包裹在需要缓存的组件外部,被缓存的组件会保留在内存中,组件下次切换时只需要从内存中读取并显示出来即可
//include---指定需要缓存的组件列表(使用时必须给组件设置name)
//exclude---指定不需要缓存的组件列表
<keep-alive include="ChildA,ChildB" exclude="ChildC">
<component :is="组件"/>
</keep-alive>
3、与keep-alive搭配使用的两个钩子函数:
deactivated//进入缓存
activated//激活组件
1、作用:自定义组件内容
2、 默认插槽:<slot/>//占位
具名插槽:<slot name=""/>
用于定义动画:<transition name="默认v" mode="出入顺序"><transition>//内部只能包裹一个标签
name:默认v,用于充当类名如:.name名-enter-from{书写动画}
mode:out-in:先入后出,in-out反之
局部指令:通过directives选项来定义,指令名:{使用钩子函数编写操作},只能在当前组件使用
全局指令:通过app.directive方法定义,指令名:{使用钩子函数编写操作},可以在任何组件使用
定义://创建一个js文件
export default(){
install(app){}
}
使用:在main.js里引入定义的插件,app.use(插件名)//use方法执行时自定执行了install方法
1、功能:抽离多个组件的公共代码(选项),将抽离的代码放在单独的文件里,需要用时引入,避免代码冗余。 //单独文件(mixins)里能写在都是已有的选项
2、使用:mixins:[名],混入的公共代码会出现在选项内
$forceUpdate()//让组件强制更新
$nextTick()//可以让特定代码在组件的下次更新周期到后再执行
1、概念:单个页面,通过地址栏地址变化,跳转不同页面实现更新页面内容的技术
2、在vite构建的vue单页面应用中,需要借助vue-router库,实现路由功能
3、配置路由表:
单条路由的配置:
{path:'/login',component:Login}
嵌套路由:
{
path:'/index',//地址后写什么
component:Index//组件
children:[]//嵌套的路由必须跟在/index/后面
},
重定向:{path:'/',redirect:'/index'}
404:{path:'/:error(.*)',component:NotFound}
4、路由组件
<router-link to="用来跳转路由">//最终渲染成a标签
router-view//充当路由渲染出口
5、路由实例:
$router//路由管理对象,负责跳路由
$route//路由对象,负责存储路由信息
6、条路由的两种方式:
标签式导航:借助router-link渲染的a标签来跳转
编程式导航:借助$router的push,go方法来跳路由
7、条路由传参:
动态路由传参:
配置路由:{path:'/detail/:id',component:Detail}
传参:this.$router.push("/detail/"+参数)
接参:this.$route.params.id
固定路由传参:
传参:this.$router.push({path:"/detail/",query:{id}});
接参:this.$route.query.id
1、概念:为了减少页面加载时间,在需要的时候再调用对应的js文件。
用懒加载方式导入每个组件,每个组件都会单独生成一个js文件,当你实际访问哪个路由,对应的组件文件才会加载,否则不加载。
2、使用:var MyIndex = () => import('../views/MyIndex.vue');
1、概念:在到跳路由前、后做的一些操作//不如跳购物车页面判断下是否登录
2.语法:
router.beforeEach((to,from,next)=>{//全局前置守卫函数
to//去往哪里的路由对象
from//来自哪里的路由对象
next('/login')//不写参数放行,写了就是强制跳该路由
})
//全局后置守卫函数
router.afterEach()
3、应用:
1)控制路由跳转
2)配合nprogress实现进度条的播放
1、概念:基于Promise的Http请求工具库,支持浏览器端和NodeJS端
2、下载axios插件、并对其进行封装
3、实例化一个axios对象,并在其上添加拦截器
var service = axios.create//1.实例化axios
service.interceptors.request.use(//2.设置 请求 拦截器
(config)=>{}, //请求从本地发给服务器之前执行
(error) => {} //请求发生错误时的处理
)
service.interceptors.response.use{//3.设置 响应 拦截器
(res)=>{}, //请求从服务器发送回来时执行
(error) => {}//对请求发生错误时的处理
}
export default service;//导出
4、配置代理
1)概念:如果不做配置,默认发送的ajax请求,会发给vscode临时开启的服务器
server: {
proxy: {//代理
'/api': {//所有以/api开头的请求都会发送给目标服务器
target: '目标服务器地址', //目标服务器
changeOrigin: true,//开始跨域
}
}
}
5、发送请求,并将每一个接口封装成一个函数,并导出//便于统一管理
封装:
export function 名(参数 = {}) {
//get
return service.get('地址', { params: 参数 })
//post
return service.post('地址', 参数 );
}
使用:
import * as service from '路径';//集体导入到一个对象中
import { login } from '路径';//命名导入( 按需导入 )
service.名({ 参数}).then((res)=>{
console.log(res.data);//数据
})
1、下载vuex插件,通过createStore实例创建一个store存储库
https://vuex.vuejs.org/zh/guide/#%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84-store
createStore({
state:{},//负责存储数据
getters:{},//定义计算方法(类似于计算属性,必须有返回值)
mutations:{},//定义同步方法(可以直接修改state中的数据)
actions:{},//定义异步方法(内部可以实行异步代码,但不能直接修改state中的数据)
modules:{},//模块化管理state中的数据
plugins:[]//配合其他插件管理state中的数据
})
2、使用(api):
this.$store.commit('同步方法名',参数)
this.$store.dispatch('异步方法名',参数)
this.$store.getters.计算方法名
3、相关插件
vuex-persistedstate//用于对state持久化存储
createLogger//日志打印插件,用于打印state数据
npm install vuex@next --save//安装vuex
npm install vuex-persistedstate//安装vuex-persistedstate
直接调用即可
plugins:[createPersistedState(),createLogger()]
1、组件通信:
父组件向子组件传值:父组件在子组件上写一个自定义属性传值,子组件通过props接收值
子组件向父组件传值:父组件在子组件上绑定自定义事件,子组件通过$emit触发事件并传值
兄弟组件传值:借用一个公共的通信对象,接收值的组件通过$on提前定义好监听事件,发送值的组件通过$emit触发事件,并传值
跨级传值:外层组件通过provide传值,内层组件通过inject接收值,外层发一次,所有内层都可接收
2、内置组件:
component//动态组件,通过is属性切换页面
keep-alive//缓存组件,include缓存,exclude不缓存
transition//动画组件,.name名-enter-from{书写动画},mode out-in先出后进
slot//插槽
3、自定义指令:
局部指令:组件内用directives:{}
全局指令:全局可用app.directive()
4、mixins//混入,抽离公共代码,避免代码冗余
1、配置:
单条路由:{path:'路由地址',component:组件名}
嵌套路由:{children:[]}
重定向:{redirect:'重定向地址'}
404:{path:'/:error(.*)',component:组件名}
2、路由组件:
router-link//渲染a标签,实现路由跳转
router-view//路由渲染出口
3、路由实例
$router//路由管理对象,负责跳路由
push()、go()、replace()
$route//路由对象,负责存储路由相关信息(地址,参数)
4、跳路由传参:
动态路由传参:params
定义:{path:'/detail/:id'}
跳路由传参:$router.push('/detail/'+参数)//参数是对象需要转字符串
接参:$route.params.id
固定路由传参:query
传参:$router.push({path:'/detail',query:{参数}})
接参:$route.query.id
5、路由懒加载://每个组件都会单独生成一个js文件,当你实际访问哪个路由,对应的组件文件才会加载
var Detail = ()=>import('文件路径')
6、守卫函数://应用:控制路由访问权限,进度条动画播放...
全局前置守卫函数:beforeEach((to, from, next)=>{}
全局后置守卫函数:router.afterEach((to, from) => {}
vant UI使用步骤:
下载vant npm i vant
下载并配置插件:npm i unplugin-vue-components -D//并配置vite.config.js
使用组件:直接在vue文件里使用
1、发送请求方式:
axios({method:'get'})
axios.get()
axios.post()
2、二次封装
实例化axios
设置请求拦截器//可以添加请求头参数,比如token
设置响应拦截器//判断错误的响应码
3、统一管理请求:一个请求封装为一个函数,并导出每个函数
1、vuex:是一个专为vue.js应用程序开发的状态管理模式+库,它采用集中式存储管理应用的所有组件的状态,并以响应的规则保证状态以一种可预测的方式发生变化。
2、store:
下载:npm i vuex
实例化: export default createStore({})
应用:import store from './store'
app.use(store)
3、核心
state:{},//负责存储数据
getters:{},//定义计算方法(类似于计算属性,必须有返回值)
mutations:{},//定义同步方法(可以直接修改state中的数据)
actions:{},//定义异步方法(内部可以实行异步代码,但不能直接修改state中的数据)
modules:{},//模块化管理state中的数据
plugins:[]//配合其他插件管理state中的数据
4、核心api
this.$store.commit('同步方法名',参数)
this.$store.dispatch('异步方法名',参数)
1、模块化管理:用于模块化管理state中的数据,每一个模块是一个独立的js文件,每个模块有自己的state、getters、mutations、actions,最终导入一个文件,进行统一管理。
2、定义和注册模块
//定义模块
export default{
namespaced:true, //让当前模块变成拥有自己独立作用域的私有模块
state:{},getters:{},mutations:{},actions:{}
}
{modules:{模块名:模块}}//注册模块:
3、使用:
//使用模块中的数据
this.$store.state.模块名.xx
this.$store.getters['模块名/xx']
//使用模块中的方法
this.$store.commit['模块名/同步方法']
this.$store.dispatch['模块名/异步方法']
概念:用于简化在组件中使用的vuex的数据和方法
1、mapState 映射到computed中
1)映射:不使用模块:
computed:{...mapState(['属性1','属性2',...])}
computed:{...mapState('模块名',['属性1','属性2',...])}
2)使用:this.属性//和普通计算属性一样,直接调用即可
2、mapGetters 映射到computed中
1)映射:不使用模块:
computed:{...mapGetters(['计算方法1','计算方法2',...])}
computed:{...mapGetters('模块名',['计算方法1','计算方法2',...])}
2)使用:this.计算方法
3、mapMutations 映射到methods中
1)映射:不使用模块:
methods:{...mapMutations(['同步方法1','同步方法2',...])}
methods:{...mapMutations('模块名',['同步方法1','同步方法2',...])}
2)使用:this.同步方法()
4、mapActions 映射到methods中
1)映射:不使用模块:
methods:{...mapActions(['异步方法1','异步方法2',...])}
methods:{...mapActions('模块名',['异步方法1','异步方法2',...])}
2)使用:this.异步方法()
1、安装第三方库
axios、element-plus、pinia-plugin-persistedstate
其他插件:plugin-auto-import、图表库、echarts
2、路由配置:
配实例化路由,并配置全局前置守卫、全局后置守卫
抽离路由配置表:routerConfig.ts
配置一级和二级路由,重定向、404、,并使用懒加载
3、网络请求:
安装,并对axios进行二次封装:实例化axios,设置请求拦截器、响应拦截器
统一管理应用程序的api接口:
使用二次封装的axios实例发送请求,分模块管理请求,一个函数一个请求
1、登录
1)表单
2)表单验证
3)表单提交
2、面包屑
1)封装为独立组件
2)数据添加到pinia
3)通过数据字典渲染
3、权限菜单的动态渲染
1)用户的权限列表
2)完整的菜单数据
3)根据用户权限列表进行过滤,进行渲染
4、轮播图管理
1)图片的增删改查
5、管理员管理
1)管理员的增删改查
2)新增和编辑共用一个表单,数据的回显和清空
6、产品管理
1)产品的增删改查
7、数据可视化
1)echarts:安装、导入、
实例化:放在挂载后,一个实例化只能绑定一个dom节点
绘图:ajax后拿到数据,进行绘图