Vue 的学习
Vue 是一个构建用户界面的渐进式框架
工程化开发 & 脚手架 Vue CLI
Vue CLI 是官方提供的一个全局命令工具
可以快速帮助我们创建一个开发Vue项目的标准化基础架子。(集成了 webpack 配置)
好处:
- 开箱即用,零配置
- 内置 babel 等工具
- 标准化
使用步骤
- 全局安装(一次)
npm i @vue/cli -g 或 yarn global add @vue/cli
- 查看 Vue 版本
vue -version
- 创建项目架子
vue create project-name
- 启动项目
npm run serve 或 yarn serve
- 显示 webpack 配置文件
vue inspect > output.js
一、创建 Vue 实例
//容器
<div id="app">
{{ msg }}
</div>
<script src="https://cdn.jsdeliver.net/npm/vue@2.7.10/dist/vue.js"></script>
<script>
const app = new Vue({
//el 指定挂载点
el: '#app',
data: {
msg: '数据'
}
})
</script>
二、Vue 指令的学习
v-html
设置元素的 innerHTML,解析 HTML 标签
语法:
v-html="表达式"
v-show
控制元素的显示与隐藏,但是占位置
语法:
v-show="表达式" //为 true 显示,false 隐藏
v-if
控制元素的显示与隐藏,条件渲染,不占位置
语法:
v-if="表达式" //为 true 显示,false 隐藏
v-else
需要紧挨着 v-if 使用
控制元素的显示与隐藏,条件渲染,不占位置
语法:
v-else //效果与紧挨着的 v-if 相反
v-else-if
需要紧挨着 v-if 使用
控制元素的显示与隐藏,条件渲染,不占位置
语法:
v-else-if="表达式" //为 true 显示,false 隐藏
v-on
注册事件
简写为:@
语法:
v-on:事件名="内联语句"
v-on:事件名="methods中的函数名"
v-for
v-for 的默认行为会原地修改元素
:key 属性
作用:给列表项添加的唯一标识。便于Vue进行列表项的正确排序复用
v-bind 绑定 class
方式一(通过布尔值进行添加):
:class="{类名: 布尔值,类名: 布尔值,...}"
方式二 (通过数组类名列表添加):
:class="["类名","类名",...]"
v-bind 对于样式控制的增强 - 操作style
语法: :style=“样式对象”
<div :style="{ CSS属性名1: CSS属性值, CSS属性名2: CSS属性值}"></div>
指令修饰符
- 按键修饰符:
@keyup.enter //键盘回车监听
- v-model 修饰符:
v-model.trim //去除首尾空格
x-model.number //转数字
- 事件修饰符
@事件名.stop //阻止冒泡
@事件名.prevent //阻止默认行为
自定义指令
指令名定义时不加 v- 但使用时要加
语法:
directives: {
//element 为绑定的标签,binding 是绑定的值
自定义指令名(element, binding) {
//指令与元素绑定时
bind() {
},
//指令所在元素被插入页面时
inserted() {
},
//指令所在的模板被重新解析时
update() {
}
}
}
过滤器
对数据进行过滤
定义
//定义全局过滤器
Vue.filter('过滤器名', function(value){
return 过滤的方法
})
//定义局部过滤器
filters: {
'过滤器名'(){
return 过滤的方法
}
}
使用
通过管道符进行过滤
管道符的作用是将左边表达式的输出作为右边表达式的输入
值 | 过滤器名
三、计算属性
基于现有的数据,计算出来的新属性
- 声明在 computed 配置项中,一个计算属性对应一个函数
computed: {
计算属性名() {
基于现有数据进行求值
return 结果
}
}
缓存特性 (提升性能):
计算属性会对计算出来的结果缓存,再次使用直接读取缓存,依赖项变化了,会自动重新计算 -> 并再次缓存
计算属性的完整写法:
能够对依赖项进行修改
computed: {
计算属性名: {
get() {
一段代码逻辑(计算逻辑)
return 结果
},
set(修改的值) {
一段代码逻辑(修改逻辑)
}
}
}
四、watch 监听器
监视数据的变化,执行一些业务逻辑 或 异步操作
简单语法:
watch: {
数据属性名 (newValue, oldValue) {
一些业务逻辑 或 异步操作
},
//对于对象
'对象.属性名' (newValue, oldValue) {
一些业务逻辑 或 异步操作
}
}
完整语法:
添加额外配置项
deep: true 对复杂类型深度的监视
immeditate: true 页面初始化时立刻执行一次handler方法
watch: {
对象数据属性名: {
deep: true, //深度监视
immeditate: true//初始化后执行
handler (newValue, oldValue) {
一些业务逻辑 或 异步操作
}
},
}
五、生命周期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8xiFJGct-1689042627888)(C:\Users\mzhj\AppData\Roaming\Typora\typora-user-images\image-20230707155325941.png)]
在创建阶段的最后 发送初始化渲染请求
在挂载阶段的最后可以开始操作 DOM
生命周期钩子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z2ytXt3R-1689042627889)(C:\Users\mzhj\AppData\Roaming\Typora\typora-user-images\image-20230707155925981.png)]
六、组件化
组件化编码流程
- 实现静态组件:抽取组件,使用组件实现静态页面效果
- 展示动态数据:数据的类型、名称是什么?数据保存在哪个组件?
- 交互——从绑定事件监听开始
非单文件组件的创建
- 每一个组件在创建时都会调用 VueComponent 函数,返回一个 VueComponent 函数的对象
- VueComponent 函数的对象进行 原型链查找时 __proto__ 都会指向 VueComponent 函数的原型对象,在 Vue 中,VueComponent 函数的原型对象的__proto__ 都会指向 Vue 的原型对象,所以组件中可以使用 Vue 中的方法和属性
<script>
//第一步创建组件
//Vue.extend可以省略,注册时还是会自动调用Vue.extend
const 组件变量 = Vue.extend({
//模板只能有一个根节点
template:`
<div>
//html 元素
</div>
`,
data(){
return {
数据属性
}
}
})
const 组件变量 = Vue.extend({
//模板只能有一个根节点
template:`
<div>
//html 元素
</div>
`,
data(){
return {
数据属性
}
}
})
//第二步注册组件(局部注册)
new Vue({
el:'#app',
components:{
组件名1:组件变量1,
组件名2:组件变量2
//当组件名与组件变量一致时,也可只写组件名
}
})
//全局注册组件
Vue.component('组件名',组件变量)
</script>
单文件组件的创建
以 .vue 结尾的文件
<templete>
//界面内容
</templete>
<script>
//交互操作,默认导出组件
export default {
//组件
}
</script>
<style>
//界面样式
</style>
七、ref 属性
- 被用来给元素或子组件注册引用信息(id的替代者)
- 应用在 html 标签上获取的是真实 DOM 元素,应用在组件标签上是组件实例对象
使用
打标识:<h1 ref="xxx"......</h1>
获取:this.$refs.xxx
子组件与父组件通信
//父组件
<template>
<子组件 ref='xxx'/>
</template>
<script>
export default {
methods: {
//要调用的方法
},
//DOM 挂载完之后使用
mounted: {
this.$refs.xxx.$on('传给子组件的事件名',this.调用的方法)
}
}
</scirpt>
子组件
//触发事件
this.$emit('事件名',传给父组件的参数...)
//解绑事件
this.$off('事件名')
//解绑多个事件
this.$off(['事件名','事件名',...])
//解绑所有
this.$off()
八、props 属性
- props 属性能够实现组件外部给组件传参数
- props 属性是优先于 data 被接收的
- props 是只读的,如果进行修改就会发出警告,如果确实需要修改,可以复制一份去 data 中修改
定义方法
//传递数据(可以传递方法)
<组件名 参数="xxx"/>
//接收数据
//只接受:
props: ['参数','参数','参数']
//限制类型:
props: {
参数: 数据类型,
参数: 数据类型
}
//限制类型、限制必要性、指定默认值
props: {
参数:{
type: 数据类型,
required: true/false,
default: '默认值'
},
参数:{
type: 数据类型,
required: true/false,
default: '默认值'
}
}
九、mixin 混入
功能:将多个组件共有的配置提取成一个混入对象
定义混合:
mixin.js
export default {
data(){...},
methods:{...},
...
}
使用混合:
import {xxx} from 'mixin.js'
//全局混合
Vue.mixin(xxx)
//局部混合
mixins:['xxx']
十、插件
功能:用于增强 Vue
本质:包含一个install 方法的对象,install 的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
定义插件
对象.install = function (Vue, options){
//插件方法
}
使用插件
Vue.use()
十一、组件自定义事件
适用于 自组件 ====> 父组件
自定义事件与 props 和 ref 属性的区别与联系
-
都能够实现子组件与父组件的通信
-
ref 的
自定义事件
//方式一
<template>
//直接将自定义事件绑定到,子组件的 VueComponet 实例上
<子组件 v-on:自定义事件名='自定义方法'>
</template>
<script>
methods:{
自定义方法() {
//处理
}
},
</script>
//方式二
<子组件 ref='xxx'>
<script>
methods:{
自定义方法() {
//处理
}
},
mounted() {
this.$ref.xxx.$on('自定义事件名',this.自定义方法)
}
</script>
使用
this.$emit('自定义事件名')
十二、全局事件总线
安装在 Vue.prototype 上的一个属性
能够实现任意两个组件之间的通信
安装:
new Vue({
......
beforeCreate() {
//安装全局事件总线,this就是当前应用的vm
Vue.prototype.$bus = this
},
.....
})
使用事件总线
- 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身
methods() {
demo(data){....}
}
....
mounted() {
this.$bus.$on('xxx',this.demo)
}
- 提供数据:
this.$bus.$emit('xxx',数据)
最好在 beforeDestroy 钩子中去解绑当前组件所用到的事件
十三、$nextTick
Vue 提供的模板
通过调用这个 API 实现让指定函数在下一次 DOM 更新结束后执行。
调用
this.$nextTick(回调函数)
当数据改变后,要基于改变的新 DOM 进行某些操作时,要在 nextTick 所指定的回调函数中执行
十四、动画
//可以设置 name 值
<transform name="">
//vue中的动画区域
</transform>
//多个动画同时设置(需要指定 key 值)
<transform-group>
<div :key=""></div>
<div :key=""></div>
</transform-group>
动画区会自动给标签加上
.v-enter-active{
//需要编写进入动画
}
//也可自己编写起点和终点
.v-enter{
//进入的起点
}
.v-enter-to{
//进入的终点
}
.v-leave-active{
//需要编写离开动画
}
//自己编写离开的起点和终点
.v-leave{
//自己编写离开的起点
}
.v-leave-to{
//自己编写离开的终点
}
十五、发送 Ajax 请求
解决跨域问题
在 vue.config.js 中配置代理服务器:
//方式一,只能配置一个服务器地址(优先匹配前端资源,不存在就请求服务器)
devServer: {
proxy: '<url>'
}
//方式二
devServer: {
proxy: {
//通过前置决定是不是走代理
'/前置': {
target: '<url>',
//去掉前置
pathRewrite: {'^/前置':''},
//用于支持WebSocket
ws: true,
//是否请求时伪装端口(默认为 true)
changeOrigin: true
},
'/前置': {
target: '<url>',
//去掉前置
pathRewrite: {'^/前置':''},
//用于支持WebSocket
ws: true,
//是否请求时伪装端口(默认为 true)
changeOrigin: true
}
}
}
十六、插槽
让父组件可以向子组件指定位置插入 html 结构,组件间通信的方式, 适用于 父组件 ===> 子组件
默认插槽
//父组件中
<组件名>
<填入的内容></填入的内容>
</组件名>
//子组件中
//组件内部,使用slot接收
<slot>//可以编写默认值</slot>
具名插槽
//父组件中
<组件名>
<填入的内容 slot="插槽名"></填入的内容>
</组件名>
//子组件中
//组件内部,使用slot接收
<slot name="插槽名">//可以编写默认值</slot>
作用域插槽
数据在子组件里,但是数据的结构需要父组件决定
//父组件中
<组件名>
//接收插槽传过来的数据,获得的是数据对象
<template slot-scope="对象名">
<填入的内容 ></填入的内容>
</template>
</组件名>
//子组件中
//组件内部先将数据传给插槽使用者,再使用slot接收,
<slot :对象名="数据名">//可以编写默认值</slot>
十七、Vuex 状态管理
概念
专门在 Vue 中实现集中式状态管理的一个 Vue 插件,对vue 应用中多个组件的共享状态进行集中式的管理,也是组件间的通信方式,且适用与任意组件间的通信。
什么时候使用?
- 多个在组件依赖于同一个状态
- 来自不同组件的行为需要变更同一状态
安装(vue2中使用3版本,vue3使用4版本)
npm i vuex
注册
import store from './store'
new Vue({
el: '#app',
render: h => h(App),
store,
})
新建 store 文件夹,新建 index.js 文件夹
Vuex 主要由三部分组成
actions、mutations、state
还有 getters
index.js文件
//引入并在 vue 中全局注册
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//用于响应组件中的动作
const actions = {
函数名(context,value) {
//要调用的方法名与值传给 mutations
context.commit('方法名', 值)
}
}
//用于操作数据
const mutations = {
方法名(state,value) {
//操作 state 中的数据
state.数据 = value
}
}
//用于存储数据
const state = {
数据:值
}
//创建 store
export default new Vuex.Store({
actions,
mutations,
state,
})
引入
import store from './store'
new Vue({
el: '#app',
render: h => h(App),
store,
})
当数据需要加工后再使用时,可以使用 getters 加工
const getters = {
处理(state) {
return state
}
}
读取 getters 中的内容
$store.getters.处理
四个 map 方法的使用
- mapState 方法:用于映射 state 中的数据为计算属性
computed: {
//写法一(对象写法)
...mapState({变量名:'映射的数据',...})
//方法二(数组写法)
...mapState(['数据名',...])
}
- mapGetters方法:用于映射 getters 中的数据为计算属性
computed: {
//写法一(对象写法)
...mapGetters({变量名:'映射的数据',...})
//方法二(数组写法)
...mapGetters(['数据名',...])
}
- mapActions方法:用于生成与 actions 的对话方式,包含 $store.dispatch(xxx) 的函数
methods: {
...mapActions({方法名:'映射的方法',...})
...mapActions(['映射的方法',...])
}
- mapMutations方法:用于生成与 mutations 的对话方式,包含 $store.commit(xxx) 的函数
methods: {
...mapMutations({方法名:'映射的方法',...})
...mapMutations(['映射的方法',...])
}
模块化编码
让代码更好维护,让数据分类明确
//引入模块
export default new Vue.store({
modules: {
模块,
...
}
})
开启命名空间
export default {
namespaced: true,//开启命名空间
actions:{},
mutations: {},
getters: {},
state: {}
}
开启命名空间后读取 state 数据
//方式一
this.$store.state.模块名.数据名
//方式二
...mapState('模块名', ['数据名',...])
开启命名空间后读取 getters 数据
//方式一
this.$store.getters['模块名/数据名']
//方式二
...mapGetters('模块名', ['数据名',...])
开启命名空间后调用 dispatch
//方式一
this.$store.dispatch('模块名/方法名', 数据)
//方式二
...mapActions('模块名', {方法名:'映射的方法',...})
开启命名空间后调用commit
//方式一
this.$store.commit('模块名/方法名', 数据)
//方式二
...mapMutations('模块名', {方法名:'映射的方法',...})
十八、vue-router 路由
vue 的一个插件库,实现 SPA 应用
单页面应用(SPA)
- 整个应用只有一个完整页面
- 点击页面中的导航链接不会刷新页面,只会做页面的局部刷新
- 数据需要通过 Ajax 请求获取
多页面
在多个页面来回跳转
安装
vue2 只能使用 vue-router 3
npm i vue-router
引用
新建 router 文件夹,新建 index.js 文件
import VueRouter from 'vue-router'
//创建路由器
const router = new VueRouter({
routes:[
{
name: '',
path: '',
component: ,
},
{},
...
]
})
export default router
使用
//页面跳转
<router-link to="/路径"></router-link>
//指定页面呈现的位置
<router-view></router-view>
每个路由组件都由自己的 route ,以及共有的 router , router 需要 $router 获取
通过 router 的 query 参数获取路由中的参数
//传递参数
<router-link :to='{
path: '完整路径',
//采用命名路由可替换 path
name: '路由name'
query:{
//传递的参数
}
}'></router-link>
通过 router 的 params 参数获取路由中的参数(声明路由时需声明接收参数)
//传递参数
<router-link :to='{
name: '路由name'
params:{
//传递的参数
}
}'></router-link>
路由的 props 参数
routes:[
{
name: '',
path: '',
component: ,
//props 第一种写法,该对象中的所有 key-value 都会以 props 的形式传给该路由组件
props:{}
//props 第二种写法,值为布尔值,若布尔值为真,就会将该路由收到的所有 params 参数,以 props 的形式传给该路由组件(只接受 params)
props:true
//props 第三种写法,值为函数
props($route) => {
return {变量:$route.query.参数,变量:$route.params.参数}
}
},
{},
...
]
路由方法
replace 替换当前路由记录
//开启 replace 模式
<router-link :replace='true'></router-link>
默认为 push
编程式路由切换
this.$router.push('')
this.$router.replace('')
//回退路由
this.$router.back()
//前进路由
this.$router.forword()
//前进或后退 num 步,负数为后退
this.$router.go(num)
缓存路由组件
作用:让不展示的组件保持挂载,不被销毁
不添加 include 则全部缓存,缓存多个使用 :include=“[]”
<keep-alive include="组件名">
<router-view></router-view>
</keep-alive>
路由的生命周期钩子
路由组件所独有的两个钩子,用于捕获路由组件的激活状态
activated()(激活时触发)
activated() {
}
deactivated()(失活时触发)
deactivated() {
}
路由守卫
路由定义
import VueRouter from 'vue-router'
//创建路由器
const router = new VueRouter({
routes:[
{
name: '',
path: '',
component: ,
//路由元信息
//设置是否需要鉴权
meta: {isAuth:thre}
},
{},
...
]
})
export default router
全局前置路由守卫
router.beforeEach((to, from, next) => {
//to:跳转去的路由
//from:当前路由
//next:执行跳转
})
全局后置路由守卫
router.afterEach((to, from) => {
//to:跳转来的路由
//from:来的路由
})
独享路由守卫
//创建路由器
const router = new VueRouter({
routes:[
{
name: '',
path: '',
component: ,
//路由元信息
//设置是否需要鉴权
meta: {isAuth:thre},
//设置独享路由守卫(只有前置)
beforeEnter: (to, from, next) => {
}
},
{},
...
]
})
组件内路由守卫
export default {
//通过路由规则进入时调用
beforeRouterEnter (to, from, next) {
},
//通过路由规则,离开时调用
beforeRouterLeave (to, from, next) {
}
}
路由的两种规则模式
hash 模式 # (默认开启)
带有 # ,# 之后的内容并不会发送给服务器
但是可能在移动端访问时会被认为是 不合法 的地址
兼容性好
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7PY0tOsd-1689042627890)(C:\Users\mzhj\AppData\Roaming\Typora\typora-user-images\image-20230710160515591.png)]
history 模式
兼容性略差
//创建路由器
const router = new VueRouter({
//设置路由模式
mode: 'history'
routes:[]
})
十九、Vue UI 组件库
移动端常用
- vant https://youzan.github.io/vant
- Cube UI https://didi.github.io/cube-ui
- Mint UI http://mint-ui.github.io
PC 端常用
- Element UI https://element.eleme.cn
- IView UI https://www.iviewui.com
router.beforeEach((to, from, next) => {
//to:跳转去的路由
//from:当前路由
//next:执行跳转
})
#### 全局后置路由守卫
```vue
router.afterEach((to, from) => {
//to:跳转来的路由
//from:来的路由
})
独享路由守卫
//创建路由器
const router = new VueRouter({
routes:[
{
name: '',
path: '',
component: ,
//路由元信息
//设置是否需要鉴权
meta: {isAuth:thre},
//设置独享路由守卫(只有前置)
beforeEnter: (to, from, next) => {
}
},
{},
...
]
})
组件内路由守卫
export default {
//通过路由规则进入时调用
beforeRouterEnter (to, from, next) {
},
//通过路由规则,离开时调用
beforeRouterLeave (to, from, next) {
}
}
路由的两种规则模式
hash 模式 # (默认开启)
带有 # ,# 之后的内容并不会发送给服务器
但是可能在移动端访问时会被认为是 不合法 的地址
兼容性好
[外链图片转存中…(img-7PY0tOsd-1689042627890)]
history 模式
兼容性略差
//创建路由器
const router = new VueRouter({
//设置路由模式
mode: 'history'
routes:[]
})
十九、Vue UI 组件库
移动端常用
- vant https://youzan.github.io/vant
- Cube UI https://didi.github.io/cube-ui
- Mint UI http://mint-ui.github.io
PC 端常用
- Element UI https://element.eleme.cn
- IView UI https://www.iviewui.com