admin 管理员组文章数量: 887018
目录
- Vue 2.x 学习笔记
- Node
- node
- 查看 node 版本
- npm
- 查看 npm 版本
- 查看 npm 当前镜像源
- 设置 npm 使用淘宝镜像源
- yarn
- 安装 yarn
- 查看 yarn 当前镜像源
- 设置 yarn 使用淘宝镜像源
- Vue CLI
- 安装
- 创建项目
- 脚手架文件结构
- 关于不同版本的 Vue
- vue.config.js 配置文件
- refs
- props
- 传递数据
- 接收数据
- 方式一:简单接收
- 方式二:限制数据类型
- 方式三
- mixin(混入)
- 第一步:定义混入
- 第二步:使用混入
- 全局混入
- 局部混入
- plugins(插件)
- 定义插件
- 使用插件
- 样式
- scoped
- 总结 TodoList 案例
- 组件化编码流程(通用)
- 实现静态组件
- 展示动态数据
- 交互:从绑定事件监听开始
- props
- props用于组件间通信
- 父传子
- 子传父
- 不能修改 props 的值
- (webStorage)浏览器本地存储
- API
- setItem
- getItem
- removeItem
- clear
- 自定义事件
- 绑定自定义事件
- 第一种方式
- 第二种方式
- 触发自定义事件
- 解绑自定义事件
- 注意
- 全局事件总线(GlobalEventBus)
- 安装全局事件总线
- 使用事件总线
- 接收数据
- 提供数据
- 解绑自定义事件
- 消息订阅与发布( pubsub-js )
- 使用步骤
- 1. 安装 pubsub 插件。
- 2. 引入 pubsub 插件。
- 3. 订阅消息
- 4. 发布消息
- 5. 最好在订阅组件的 beforeDestroy 钩子函数中,取消订阅。
- $ nextTick 实例方法
- 语法
- 作用
- 应用场景
- Vue 封装的 过渡 & 动画
- 使用 CSS 动画
- 准备动画
- 准备样式
- 使用 `<transition>`标签
- 使用 `<transition-group>`标签
- 使用 CSS 过渡
- 1. 准备样式
- 2. 使用 `<transition>` 或 `<transition-group>` 标签
- 配合使用第三方动画库 `Animate.css`
- Vue 中的 ajax
- Vue 脚手架配置代理服务器 devServer
- 方法一
- 方法二
- vue - router
- 基本概念
- vue - router
- SPA 应用
- 路由 `route`
- 后端路由
- 前端路由
- 基本使用
- 安装 vue-router 插件
- 引入
- 应用
- 编写 router 配置项
- 在 Vue 实例中,加入 router 配置项。
- `router-link` 标签:实现路由切换
- `router-view` 标签:指定组件的呈现位置,路由占位符
- 注意
- 多级路由(嵌套路由)
- 配置路由规则,使用 `children` 配置项。
- 路由切换
- 路由的 query 参数
- 传递参数
- 属性 to 的字符串写法
- 属性 to 的对象写法
- 接收参数
- 命名路由
- 为路由命名
- 简化跳转
- 路由的 params 参数
- 配置路由,声明接收 params 参数。
- 传递参数
- 接收参数
- 路由的 props 配置
- 接收参数
- 写法一
- 写法二
- 写法三
- `<router-link>` 标签的 push/replace 属性
- 编程式路由导航
- 缓存路由组件
- 两个路由独有的生命周期钩子
- `activated`
- `deactivated`
- 路由守卫
- 分类
- 全局路由守卫
- 全局前置路由守卫
- 全局后置路由守卫
- 独享路由守卫
- 组件内路由守卫
- `beforeRouteEnter(to, from, next)`
- `beforeRouteLeave(to, from, next)`
- 路由器的两种工作模式
- hash 值
- 路由模式
- hash 模式(默认)
- history 模式
- 补充内容
- ESLint
- 配置
- 查看 webpack 所有版本
- 查看 less-loader@11 依赖的包与版本
- 安装 less-loader
- 安装 less
- 安装 nanoid ( uuid 的简化版 )
- 一个重要的内置关系
- Object.hasOwn()
- 语法
- 参数
- 返回值
- CSS3 动画
- 1. 定义动画(@keyframes)
- 2. 在样式中使用动画(animation)
- 3. 在元素中应用样式
- 浏览器发送网络请求
- 跨域问题 XMLHttpRequest
- 解决方法
- 跨域问题报错信息
- Node + Express 搭建测试服务器
- 在搭建好的服务器端解决 history 模式刷新页面 404 问题
- ElementUI
- 按需引入
- 安装 babel-plugin-component
- 修改 babel.config.js 文件
- 按需引入
Vue 2.x 学习笔记
Node
node
查看 node 版本
node -v
# v16.19.0
npm
查看 npm 版本
npm -v
# 8.19.3
查看 npm 当前镜像源
npm config get registry
设置 npm 使用淘宝镜像源
npm config set registry https://registry.npmmirror/
yarn
安装 yarn
临时使用淘宝镜像全局安装 yarn
npm install -g yarn --registry=https://registry.npm.taobao
查看 yarn 当前镜像源
yarn config get registry
# https://registry.npmmirror/ 表明已成功永久配置成淘宝镜像源
设置 yarn 使用淘宝镜像源
yarn config set registry https://registry.npmmirror/
Vue CLI
安装
npm install -g @vue/cli
# OR
yarn global add @vue/cli
创建项目
vue create my-project # 命令行创建
# OR
vue ui # 使用 GUI 创建
脚手架文件结构
├── node_modules
├── public
│ └── favicon.ico 页签图标
│ └── index.html 主页面
├── src
│ └── assets 存放静态资源
│ ├── logo.png
│ └── component 存放组件
│ ├── HelloWorld.vue
│ ├── App.vue 汇总所有组件
│ ├── main.js 入口文件
├── .gitignore git版本管制忽略的配置
├── babel.config.js babel的配置文件(用于ES6->ES5)
├── package.json 应用包配置文件
├── package-lock.json 包版本控制文件
└── README.md 应用描述文件
关于不同版本的 Vue
-
vue.js
与vue.runtime.xxx.js
的区别:-
vue.js
是完整版的 Vue,包含核心功能
+模板解析器
。 -
vue.runtime.xxx.js
是运行版的 Vue,只包含核心功能
,不包含模板解析器
。
-
-
因为 vue.runtime.xxx.js 没有模板解析器,所以在入口文件 main.js 中,不能使用 template 配置项,需要使用 render 函数接收到的 createElement 函数去指定具体内容。
vue.config.js 配置文件
-
在终端输入命令
vue inspect > output.js
,可以在根目录下,生成output.js
文件,在此文件中可以查看 Vue 脚手架的默认配置。注意:报错是因为,文件中是一个对象,在文件在前面加上
export default
即可。 -
使用
vue.config.js
可以对脚手架进行个性化定制,详情见 https://cli.vuejs/zh 。
refs
-
被用来给元素或子组件注册引用信息(id的替代者)。
-
应用在 html 标签上获取的是
真实 DOM 元素
,应用在组件标签上获取的是组件实例对象(vc)
。 -
使用方式:
-
打标识
<h1 v-text="msg" ref="title"></h1> <button @click="showDOM" ref="btn">点我输出上方的 DOM 元素</button> <School ref="sch" />
-
获取 ref
this.$refs.title // 真实 DOM 元素 this.$refs.btn // 真实 DOM 元素 this.$refs.sch // School 组件的实例对象(vc)
-
props
让组件接收外部传来的数据。
传递数据
<Student name="张三" sex="男" :age="20" />
接收数据
方式一:简单接收
props: ['name', 'age', 'sex']
方式二:限制数据类型
props:{
name: String,
sex: String,
age: Number
}
方式三
- 限制数据类型
- 限制数据必要性
- 指定数据默认值
props: {
name: {
type: String, // name的类型是字符串
required: true, // name是必要的
},
age: {
type: Number,
default: 99, // 默认值
},
sex: {
type: String,
required: true,
}
}
备注:props 是只读的,Vue 底层会监测你对 props 的修改。如果进行了修改,会在控制台发出警告。若业务需要确需修改,可以复制 props 内容到 data 中一份,然后再去修改 data 中的响应数据。
mixin(混入)
可以把多个组件的配置,提取成一个 mixin 混入对象。
第一步:定义混入
-
创建 mixin.js 文件。
{ data() {...}, methods: {...}, mounted() {...}, ... }
第二步:使用混入
全局混入
在 main.js 中
// 引入 mixin
import { mixin, mixin2 } from './mixin'
// 全局应用 mixin
Vue.mixin(mixin).mixin(mixin2)
局部混入
在单个 vue 文件中
import { mixin, mixin2 } from '../mixin'
export default {
mixins: [mixin, mixin2]
}
plugins(插件)
功能:用于增强 Vue。
本质:包含 install 方法的一个对象,install 的第一个参数是 Vue 构造函数,第二个参数是插件使用者传入的数据。
定义插件
在 src
目录下,创建 plugins.js
文件。
export default {
install(Vue,...options) { // options数组接收调用者传递的其他参数,如Vue.use(plugins,1,2,3),则 options = [1,2,3]
// 1. 添加全局过滤器
Vue.filter(...)
// 2. 添加全局自定义指令
Vue.directives(...)
// 3. 配置全局混入
Vue.mixin(...)
// 4. 添加实例方法
Vue.prototype.myMethod = function() {...}
Vue.prototype.myProperty = xxx
}
}
使用插件
在 main.js
文件中:
// 引入插件
import plugins from './plugins'
// 应用插件
Vue.use(plugins)
样式
scoped
让样式局部生效,防止冲突。
<style scoped>
备注:App.vue 中样式不加 scoped。
总结 TodoList 案例
组件化编码流程(通用)
实现静态组件
抽取组件,使用组件实现静态页面效果。
组件要按照功能点拆分,命名不要与 html 元素冲突。
展示动态数据
- 数据的名称、类型是什么?
- 数据保存在哪个组件中?
考虑好数据的存放位置,数据是单个组件用,还是多个组件用。
- 单个组件用:放在组件自身即可。
- 多个组件用:放在他们共同的父组件上。
(状态提升)
交互:从绑定事件监听开始
props
props用于组件间通信
父传子
- 通过 props 传递。
子传父
- 父亲先偷偷给儿子传个函数,当儿子需要传递数据给父亲的时候,调用这个函数,通过函数参数传递数据。
不能修改 props 的值
- 使用 v-modal 时要注意,v-modal 绑定的值不能时 props 传过来的值,因为 props 是不可以修改的。
- 若 props 传过来的值是对象类型,修改对象中的属性时 Vue 不会报错,但
不推荐
这样做。
(webStorage)浏览器本地存储
- 存储内容大小一般支持 5MB 左右(不同的浏览器可能不一样)
- 浏览器通过 Windows.localStorage 和 Windows.sessionStorage 来实现本地存储机制。
- sessionStorage 存储的内容会随着浏览器窗口的关闭而清除。
- localStorage 存储的内容,关闭窗口不会自动清除。需要手动清缓存或借助API才会清除。
API
setItem
//该方法接收一个键值对作为参数,会把键值以字符串的格式(调用自身的toString()方法)添加到存储中。
//如果键名存在,则更新其对应的值。
localStorage.setItem('key', 'value')
sessionStorage.setItem('key', 'value')
示例
// String 类型
localStorage.setItem('msg', '你好啊。') // '你好啊。'
// Number 类型
localStorage.setItem('number', 666) // '666'
// 对象类型
let person = { name: '张三', age: 18 }
localStorage.setItem('person', person) // '[object Object]'
localStorage.setItem('person', JSON.stringify(p)) // '{"name":"张三","age":18}'
getItem
// 该方法接收一个键名作为参数,返回键名对应的值。
localStorage.getItem('key')
sessionStorage.getItem('key')
备注
// 获取缺失的键名,会返回 null
localStorage.getItem('msg3') // null
JSON.parse(null) // null
removeItem
// 该方法接收一个键名作为参数,并将响应键值对从村粗中删除。
localStorage.removeItem('key')
sessionStorage.removeItem('key')
clear
// 清空存储中的所有数据。
localStorage.clear()
sessionStorage.clear()
自定义事件
一种组件间通信的方式,适用于
子组件
向父组件
传递数据。
绑定自定义事件
在
父组件
中给子组件
绑定自定义事件。(事件的回调在父组件
中)
第一种方式
// 在父组件中。
<Student @demo="sayHello" />
<Student v-on:demo="sayHello" />
<Student v-once:demo="sayHello" /> // 只触发一次
第二种方式
// 在父组件中。
<Student ref="student" />
...
mounted(){
this.$refs.student.$on('demo',this.sayHello)
this.$refs.student.$once('demo',this.sayHello) // 只触发一次
}
触发自定义事件
在
子组件
中触发自定义事件。
// 在子组件中。
this.$emit('demo',value) // value为传递的数据
解绑自定义事件
在
子组件
中解绑自定义事件。
// 在子组件中。
this.$off('getStudentName') // 解绑单一自定义事件。
this.$off(['getStudentName', 'demo']) // 解绑多个自定义事件。
this.$off() // 解绑所有自定义事件。
注意
-
在自定义组件中,绑定
原生 DOM 事件
,需要使用native
修饰符。(不然会被 Vue 当作自定义事件。)<Student @click.native="showInfo" />
-
通过
this.$refs.xxx.$on('自定义事件名称',callbackFn)
绑定自定义事件时,callbackFn 要么配置在父组件的 methods 中,要么使用箭头函数,否则 this 指向会出问题。-
情况一
callbackFn 没有定义在 methods 中,并且没有使用箭头函数,则函数内的 this 指向子组件实例对象。
mouted(){ this.$refs.student.$on('getStudentName', function (name, ...params) { console.log(this) // this指向Student组件实例对象 }) }
-
情况二
callbackFn 没有定义在 methods 中,但使用箭头函数,则函数内的 this 指向当前组件实例对象。
mouted(){ this.$refs.student.$on('getStudentName', (name, ...params) => { console.log('App收到了学生名称:', name, params) this.studentName = name // this指向App组件实例对象,因为箭头函数没有自己的this,所以会向父元素找。 }) }
-
情况三
callbackFn 定义在 methods 中,则函数内的 this 指向当前组件实例对象。
methods:{ getStudentName(name) { this.studentName = name // this指向App的组件实例对象 } } mouted(){ this.$refs.student.$on('getStudentName', this.getStudentName) }
-
全局事件总线(GlobalEventBus)
一种组件之间的通信方式,适用于
任意组件间传递数据
。
安装全局事件总线
// 在 main.js 中
new Vue({
...
beforeCreate(){
Vue.prototype.$bus = this // 安装全局事件总线,$bus就是当前应用的vm
}
...
})
使用事件总线
接收数据
A 组件想接收数据,则在 A 组件中给 $bus 绑定自定义事件,事件的
回调函数
留在A 组件
自身。
// 在 A 组件中。
methods:{
// 回调函数
callbackFn(data){ ... }
}
...
mounted() {
// 给 $bus 绑定自定义事件hello
this.$bus.$on('hello', this.callbackFn)
}
提供数据
// 在想要提供数据的组件内。
this.$bus.$emit('hello', data) // data 为提供的数据
解绑自定义事件
最好在
beforeDestroy
钩子中,用 $off 去解绑当前组件所用到的自定义事件。
在哪个组件绑定的,就在哪个组件解绑。
// 在 A 组件中。
beforeDestroy(){
this.$bus.$off('hello')
}
消息订阅与发布( pubsub-js )
- 订阅消息:消息名
- 发布消息:消息内容
- 退订消息:消息 ID
一种组件之间的通信方式,适用于
任意组件间传递数据
。
使用步骤
1. 安装 pubsub 插件。
npm i pubsub-js
yarn add pubsub-js
2. 引入 pubsub 插件。
import pubsub from 'pubsub-js'
3. 订阅消息
A 组件想接收数据,则在 A 组件中订阅消息,订阅的 callbackFn 留在 A 组件自身。
// 在 A 组件中。
methods(){
demo(callbackFn){ ... }
}
...
mounted() {
this.pid = pubsub.subscribe('hello',this.callbackFn) //订阅消息
}
4. 发布消息
// 在 B 组件中。
pubsub.publish('hello',data) // hello为发布的消息名,data为发布的消息数据。
5. 最好在订阅组件的 beforeDestroy 钩子函数中,取消订阅。
// 在 A 组件中。
beforeDestroy() {
pubsub.unsubscribe(this.pid) //取消订阅
}
$ nextTick 实例方法
语法
this.$nextTick(callbackFn)
作用
在下一次 DOM 更新结束后执行其指定的回调。
应用场景
当改变数据后,要基于更新后的新DOM进行某些操作时,要在 nextTick 所指定的回调函数中执行。
Vue 封装的 过渡 & 动画
在插入、更新或移除 DOM 时,在合适的时机给元素动态添加响应式样式类。
-
元素进入样式
-
v-enter:进入的起点
-
v-enter-active:进入过程中
-
v-enter-to:进入的终点
-
-
元素离开样式
-
v-leave:离开的起点
-
v-leave-active:离开过程中
-
v-leave-to:离开的终点
-
使用 CSS 动画
准备动画
使用 @keyframes 定义一个动画。
@keyframes fairy {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
准备样式
/* 没有在 template 标签中配置 name 属性 */
.v-enter-active {
animation: fairy 0.5s linear;
}
.v-leave-active {
animation: fairy 0.5s reverse linear;
}
/* 没有在 template 标签中配置 name 属性值为 hello */
.hello-enter-active {
animation: fairy 0.5s linear;
}
.hello-leave-active {
animation: fairy 0.5s reverse linear;
}
使用 <transition>
标签
<transition name='hello' appear>
<h1 v-show='isShow'>你好啊!</h1>
</transition>
- appear属性表示一上来就应用样式。
使用 <transition-group>
标签
如果有多个元素需要同时应用同一动画,则需要使用
<transition-group>
标签。
<transition-group name="hello" appear>
<h1 v-show="isShow" key="1">你好啊</h1>
<h1 v-show="!isShow" key="2">小仙女</h1>
</transition-group>
- 注意:每个元素都要指定
key
值。
使用 CSS 过渡
1. 准备样式
/* 进入的起点,离开的终点 */
.hello-enter,
.hello-leave-to {
transform: translateX(-100%);
}
/* 进入的终点,离开的起点 */
.hello-enter-to,
.hello-leave {
transform: translateX(0);
}
/* 进入过程中,离开过程中 */
.hello-enter-active,
.hello-leave-active {
transition: 0.5s linear;
}
2. 使用 <transition>
或 <transition-group>
标签
同上略。
配合使用第三方动画库 Animate.css
安装
yarn add animate.css
引入
import 'animate.css'
使用
<transition-group
appear
name="animate__animated "
enter-active-class="animate__swing"
leave-active-class="animate__backOutDown"
>
<h1 v-show="isShow" key="1">你好啊</h1>
<h1 v-show="!isShow" key="2">小仙女</h1>
</transition-group>
Vue 中的 ajax
Vue 脚手架配置代理服务器 devServer
解决发送 ajax 请求的跨域问题。
方法一
在vue.config.js中添加如下配置:
devServer: {
proxy: 'http://localhost:5000' // 目标服务器
}
请求时:
// 前端 App 运行的服务器地址为 http://localhost:8080/
axios.get('http://localhost:8080/students').then(...)
备注:
-
当请求的资源前端没有时,才会转发给目标服务器。(即优先请求前端资源)
- 如果
-
优点:配置简单,请求资源时直接发给前端(8080)即可。
-
缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
public 文件夹相当于 localhost:8080 的根路径。
方法二
在vue.config.js中添加如下配置:
module.exports = {
devServer: {
proxy: {
'/api1': {// 匹配所有以 '/api1'开头的请求路径
target: 'http://localhost:5000',// 代理目标的基础路径
changeOrigin: true,
pathRewrite: {'^/api1': ''} // 重写请求路径,将'/api'替换成''
},
'/api2': {// 匹配所有以 '/api2'开头的请求路径
target: 'http://localhost:5001',// 代理目标的基础路径
changeOrigin: true,
pathRewrite: {'^/api2': ''}
}
}
}
}
/*
changeOrigin 设置为 true 时,服务器收到的请求头中的 host 为:localhost:5000
changeOrigin 设置为 false 时,服务器收到的请求头中的 host 为:localhost:8080
changeOrigin 默认值为 true
*/
备注:
- changeOrigin 设置为 true 时,服务器收到的请求头中,host 为 localhost:5000
- changeOrigin 设置为 false 时,服务器收到的请求头中,host 为 localhost:8080(与本地相同)
- changeOrigin 默认值为 true 。
vue - router
基本概念
vue - router
vue 的一个插件库,专门用来实现 SPA 应用。
SPA 应用
- 单页 Web 应用
SPA (singe page web application)
- 整个应用只有
一个完整的页面
。- 点击页面中的导航链接
不会整体刷新
页面,只会做页面组件的局部刷新
。- 数据需要通过 ajax 请求获取。
路由 route
一个路由
route
就是一组映射关系(key
-value
)。多个路由需要
路由器 router
来管理。
key
为路径,value
可能是function
或component
。
后端路由
- value 是 function,用于处理客户端提交的请求。
- 工作过程:服务器收到一个请求时,根据
请求路径
找到匹配的函数
来处理请求,返回响应数据。
前端路由
- value 是 component,用于展示页面内容。
- 工作过程:当浏览器的路径改变时,对应的组件就会显示。
基本使用
安装 vue-router 插件
yarn add vue-router@3 # 安装 vue-router3 的最新版本
备注:
- vue-router4 只能在 vue3 中使用。
- Vue-router3 才能在 vue2 中使用。
引入
在 main.js 中
// 引入 VueRouter
import VueRouter from 'vue-router'
应用
在 main.js 中
// 应用插件 VueRouter
Vue.use(VueRouter)
编写 router 配置项
在 src 目录下创建 router 文件夹,新建 index.js 文件。
// 该文件用于创建整个应用的路由器
// 引入 VueRouter
import VueRouter from 'vue-router'
// 引入需要被路由的组件
import Home from '../components/Home'
import About from '../components/About'
// 创建 router 实例对象,来管理一组一组路由规则。
const router = new VueRouter({
routes: [
{
path: '/home',
component: Home,
},
{
path: '/about',
component: About,
},
],
})
// 默认暴露 router 实例对象
export default router
在 Vue 实例中,加入 router 配置项。
在 main.js 中
new Vue({
render: h => h(App),
router: router
}).$mount('#app')
// 简写成
new Vue({
render: h => h(App),
router
}).$mount('#app')
router-link
标签:实现路由切换
<router-link class="list-group-item" active-class="active" to="/about">About</router-link>
<router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
- to 属性:路由跳转的目标路径。
- active-class 属性:可配置选中样式。
router-view
标签:指定组件的呈现位置,路由占位符
<router-view />
注意
- 路由组件通常放在
pages
文件夹中,一般组件通常放在components
文件夹中。 - 通过切换,被隐藏的路由组件,默认是被销毁了的,需要的时候再去重新挂载。
- 每个组件实例身上都有
$route
属性,里面存储自己的路由配置信息。 - 整个应用只有一个
router
,可以通过组件实例的$router
属性获取。
多级路由(嵌套路由)
配置路由规则,使用 children
配置项。
// 在 router/index.js 文件中
routes:[
{
path:'/about',
component:About,
},
{
path:'/home',
component:Home,
children:[ //通过children配置子级路由
{
path:'news', //此处一定不要写:/news
component:News
},
{
path:'message', //此处一定不要写:/message
component:Message
}
]
}
]
路由切换
<router-link to="/home/news">News</router-link>
注意:to 属性值要写完整路径
。
路由的 query 参数
传递参数
属性 to 的字符串写法
在跳转的组件中:
<!-- 跳转并携带 query 参数,to 的字符串写法 -->
<router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link>
<!-- 模板字符串 -->
<router-link :to="`/home/message/detail?id=${message.id}&title=${message.title}`">
{{ message.title }}
</router-link>
属性 to 的对象写法
<router-link
:to="{
path: '/home/message/detail',
query: {
id: message.id,
title: message.title,
}
}"
>{{ message.title }}</router-link>
接收参数
在被跳转的组件中:
<template>
<ul>
<li>编号:{{ this.$route.query.id }}</li>
<li>标题:{{ this.$route.query.title }}</li>
</ul>
</template>
命名路由
作用:可以通过为路由命名,简化路由的跳转。
为路由命名
在 src/router/index.js 文件中:
routes: [
{
path: '/home',
component: Home,
children: [
{
path: 'message',
component: Message,
children: [
{
name: 'detail', // 为三级路由命名
path: 'detail',
component: Detail,
},
],
},
],
},
],
简化跳转
<!--简化前,需要写完整的路径 -->
<router-link to="/home/message/detail">跳转</router-link>
<!--简化后,直接通过名字跳转 -->
<router-link :to="{name:'detail'}">跳转</router-link>
<!--简化写法配合传递参数 -->
<router-link
:to="{
name: 'detail',
query: {
id: message.id,
title: message.title,
}
}"
>{{ message.title }}</router-link>
路由的 params 参数
配置路由,声明接收 params 参数。
routes: [
{
path: '/home',
component: Home,
children: [
{
path: 'message',
component: Message,
children: [
{
name: 'detail',
path:'detail/:id/:title', //使用占位符声明接收params参数
component: Detail,
},
],
},
],
},
]
传递参数
<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
<!-- 跳转并携带params参数,to的对象写法 -->
<router-link
:to="{
name:'detial',
params:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
特别注意
路由携带 params 参数时,若使用 to 的对象写法,则不能使用 path 配置项,必须使用 name 配置项。
接收参数
<template>
<ul>
<li>编号:{{ this.$route.params.id }}</li>
<li>标题:{{ this.$route.params.title }}</li>
</ul>
</template>
路由的 props 配置
作用:让路由组件更方便地收到参数。
routes: [
{
path: '/home',
component: Home,
children: [
{
path: 'message',
component: Message,
children: [
{
name: 'detail',
path:'detail/:id/:title', //使用占位符声明接收params参数
component: Detail,
// 写法一:props 值为对象,该对象中所有的 key-value 的组合最终都会通过 props 传给 Detail 组件。
props:{a:900,b:'hello'}
// 写法二:props 值为布尔值,当布尔值为 true 时,则会把路由收到的所有 params 参数通过 props 传给 Detail 组件。
props:true
// 写法三:props 值为函数,该函数返回一个对象,对象中每一对 key-value 都会通过 props 传给 Detail 组件。
props(route){
return {
id:route.query.id,
title:route.query.title
}
}
// 等同于
props({query}){ // ES6 解构赋值
return {
id:query.id,
title:query.title
}
}
// 等同于
props({ query: { id, title } }) { // ES6 解构赋值
return {
id: id,
title: title,
}
}
}
]
}
]
}
]
接收参数
在 Detail.vue 文件中:
写法一
<template>
<ul>
<li>{{ a }}</li> <!-- 900 -->
<li>{{ b }}</li> <!-- hello -->
</ul>
</template>
<script>
export default {
name: 'Detail',
props: ['a', 'b'] // 写法一:接收 props 对象中配置的 key
}
</script>
写法二
<template>
<ul>
<li>编号:{{ id }}</li>
<li>标题:{{ title }}</li>
</ul>
</template>
<script>
export default {
name: 'Detail',
props: ['id', 'title'] // 写法二:接收 params 参数
}
</script>
写法三
在 Message.vue 文件中:
<router-link
:to="{
name: 'detail',
query: {
id: message.id,
title: message.title,
},
}"
>跳转</router-link>
注意:必须使用 name 配置项。
在 Detail.vue 文件中:
<template>
<ul>
<li>编号:{{ id }}</li>
<li>标题:{{ title }}</li>
</ul>
</template>
<script>
export default {
name: 'Detail',
props: ['id', 'title'] // 写法二:接收 props 函数返回对象中的 key
}
</script>
<router-link>
标签的 push/replace 属性
-
作用:控制路由跳转时,操作浏览器历史记录的模式。
-
浏览器的历史记录有两种写入方式:
push
:追加历史记录。(压栈)replace
:替换当前记录。
-
默认为 push 模式,开启 replace 模式
<router-link replace ...>News</router-link> <!-- OR --> <router-link :replace='true' ...>News</router-link>
编程式路由导航
不借助 实现路由跳转,让路由跳转更加灵活。
// $router 的两个 API
this.$router.push({
name:'detail',
params:{
id:xxx,
title:xxx
}
})
this.$router.replace({
name:'detail',
params:{
id:xxx,
title:xxx
}
})
this.$router.forward() // 前进
this.$router.back() // 后退
this.$router.go(-2) // 后退两步
this.$router.go(3) // 前进三步
缓存路由组件
作用:让不展示的路由组件保持挂载,不被销毁。
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
<keep-alive :include="['News','Message']">
<router-view></router-view>
</keep-alive>
备注:include的值为 组件名
。
两个路由独有的生命周期钩子
路由组件所独有的两个生命周期钩子,用于捕获路由组件的
激活状态 activated
与失活状态 deactivated
。
activated
- 路由组件被激活时触发。
deactivated
- 路由组件失活时触发。
路由守卫
作用:对路由进行权限控制。
分类
- 全局路由守卫
- 独享路由守卫
- 组件内路由守卫
全局路由守卫
写在 router/index.js 文件中,在 export default router 之前。
全局前置路由守卫
- 何时被调用
- 初始化时被调用。
- 每次路由切换
前
被调用。
router.beforeEach((to, from, next) => {
console.log('全局前置路由守卫被调用了。')
console.log('beforeEach', to, from)
if (to.meta.isAuth) { // 判断当前路由是否需要权限控制
if (localStorage.getItem('school') === 'dlut') { // 权限控制的具体规则
next() // 放行
} else {
alert('暂无权限查看!')
// next({ name: 'about' }) // 跳转到 About.vue 组件
}
} else {
next() // 放行
}
})
全局后置路由守卫
-
何时被调用
-
初始化时被调用。
-
每次路由切换
后
被调用。 -
后置路由守卫没有
next
函数。
-
router.afterEach((to, from) => {
console.log('全局后置路由守卫被调用了。')
console.log('afterEach', to, from)
if(to.meta.title){
document.title = to.meta.title // 修改网页的 title
}else{
document.title = 'vue-demo'
}
})
独享路由守卫
- 某个路由所独享的路由守卫。
- 写在具体的路由配置中。
- 路由切换前被调用。
- 只有前置路由守卫,没有后置路由守卫。
// router/index.js 文件中
{
name: 'news',
path: 'news',
component: News,
meta: { isAuth: true, title: '新闻' },
beforeEnter: (to, from, next) => {
console.log(to, from, next)
if (localStorage.getItem('school') === 'dlut') {
next() // 放行
} else {
alert('暂无权限查看!')
}
}
}
组件内路由守卫
beforeRouteEnter(to, from, next)
- 进入守卫:通过路由规则,进入该组件时被调用。
beforeRouteEnter(to, from, next) {
console.log('beforeRouteEnter', to, from)
next()
}
beforeRouteLeave(to, from, next)
- 离开守卫:通过路由规则,离开该组件时被调用。
beforeRouteLeave(to, from, next) {
console.log('beforeRouteLeave', to, from)
next()
}
路由器的两种工作模式
hash 值
- 对于一个 url 来说,
#
及其后面的内容就是 hash 值。 - hash 值不会包含在 HTTP 请求中,即 hash 值不会作为路径的一部分发送给服务器。
路由模式
hash 模式(默认)
- 地址中带有
#
,不美观。 - 若以后地址通过第三方手机 app 分享,若 app 校验严格,则地址会被标记为不合法。
- 兼容性较好。
history 模式
const router = new VueRouter({
mode: 'history',
routes:[...]
})
- 地址中没有
#
,简洁美观。 - 兼容性和 hash 模式相比略差。
- 应用部署上线时,需要后端支持,解决刷新页面服务端 404 问题。
补充内容
ESLint
配置
使用 JavaScript、JSON 或 YAML 文件指定整个目录及其所有子目录的配置信息。
-
方法一:
.eslintrs.*
文件。 -
方法二:
package.json
文件中的eslintConfig
字段。 -
"eslintConfig": { "rules": { "vue/multi-word-component-names":"off" /* 关闭组件驼峰命名校验规则 */ } }
查看 webpack 所有版本
npm view webpack versions
查看 less-loader@11 依赖的包与版本
npm view less-loader@11 peerDependencies
安装 less-loader
yarn add less-loader 安装最新版本
yarn add less-loader@10 安装最近一个10版本
安装 less
yarn add less
安装 nanoid ( uuid 的简化版 )
yarn add nanoid
一个重要的内置关系
VueComponent.prototype.__proto__ === Vue.prototype
意义:让组件实例对象(vc),可以访问到 Vue 原型上的属性、方法。
Object.hasOwn()
如果指定的对象自身有指定的属性,则静态方法
Object.hasOwn()
返回true
。如果属性是继承的或者不存在,该方法返回false
。
语法
Object.hasOwn(obj, prop)
参数
- obj:要校验的对象。
- prop:要测试属性的
String
类型的名称。
返回值
如果指定的对象中直接定义了指定的属性,则返回 true
;否则返回 false
。
CSS3 动画
1. 定义动画(@keyframes)
/* 定义一个动画 */
@keyframes fairy {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
2. 在样式中使用动画(animation)
.enter {
/* 0.5s匀速播放刚刚定义的动画 */
animation: fairy 0.5s linear;
}
3. 在元素中应用样式
<h1 class="enter">你好啊!</h1>
浏览器发送网络请求
- xhr
- jQuery
- 对 xhr 的封装
- 核心是封装DOM操作(80%左右),其他只占 20% 左右。
- 不推荐
- axios
- 对 xhr 的封装
- Promise
- Vue 尤雨溪官方推荐
- jQuery
- fetch
- 优点:和 xhr 平级
- 缺点
- 包两层 Promice
- 兼容性差,不支持 IE 浏览器。
跨域问题 XMLHttpRequest
浏览器发送网络请求时,违背了
同源策略
。同源策略规定了以下内容必须保持一致:
- 协议名
- 主机名
- 端口号
备注:跨域并不是无法发送请求,实际上,请求已经发送,服务器也接收了请求,并且返回了数据,但是因为存在跨域问题,无法让请求方接收。
解决方法
-
CORS:后端解决,是真正意义上的解决跨域。
不用前端人员去做任何事情,需要后端人员在返回响应的时候,加几个特殊的响应头。
-
jsonp
原理
- 借助 script 标签里面的 src 属性在引入外部资源时,不受同源策略限制的特点。
缺点:
- 需要前后端配合,实际开发中应用很少。
- 只能解决 Get 请求的跨域问题。
-
配置代理服务器
备注:服务器与服务器之间传递数据,不用 ajax,而是用 http 请求,不存在跨域问题。ajax 是前端独有技术,ajax 才会出现跨域问题。
- nginx 开启代理服务器
- vue cli 开启代理服务器
跨域问题报错信息
Node + Express 搭建测试服务器
-
创建一个空文件夹 demo-server
-
用 vscode 打开文件夹
-
执行命令 npm init
-
安装 express
yarn add express
- 新建 server.js
// 引入 express
const express = require('express')
// 创建实例对象
const app = express()
app.use(express.static(__dirname + '/static'))
app.get('/person', (req, res) => {
res.send({
name: 'tom',
age: 18,
})
})
app.listen(5005, err => {
if (!err) console.log('服务器启动成功了。')
})
-
将打包好的 dist 文件夹下的文件复制到 static 文件夹中
-
启动服务器
node server.js
-
在浏览器中访问 http://localhost:5005 即可运行打包后的 vue 应用。
在搭建好的服务器端解决 history 模式刷新页面 404 问题
-
借助 connect-history-api-fallback 中间件
-
安装
yarn add connect-history-api-fallback
-
在 server.js 中引入
// 引入 connect-history-api-fallback 中间件 const history = require('connect-history-api-fallback')
-
应用
app.use(history())
注意:需在静态资源之前应用。
-
启动服务器
node server.js
-
访问部署后的应用,验证问题已解决。
ElementUI
按需引入
安装 babel-plugin-component
yarn add babel-plugin-component -D
修改 babel.config.js 文件
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
['@babel/preset-env', { modules: false }]
],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk',
}
]
]
}
按需引入
// 在 main.js 中
// 按需引入
import { Button } from 'element-ui'
// 应用 ElementUI
Vue.component(Button.name,Button)
// or
Vue.use(Button)
版权声明:本文标题:Vue 2.x 学习笔记 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1729002009h1305495.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论