pnpm安装
bash
# 全局安装pnpm
npm i pnpm -g
# 查看pnpm版本
pnpm -v
VueRouter使用步骤
javascript
// 1. 下载vue-touer 3.6.5
// 2. 引入VueRouter
// 3. Vue.use()
// 4. 创建router实例
// 5. 挂载到vue根实例上
Vue.use()
Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:
javascript
export function initUse(Vue: GlobalAPI) {
// Vue.use 是一个函数
Vue.use = function (plugin: Function | any) {
// 声明一个数组
const installedPlugins =
this._installedPlugins || (this._installedPlugins = [])
// 判断这个插件是否注册过,如果注册过,return
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters
// 获取其他参数 例如: Vue.use(plugin,a,b,c) 中的 a b c
const args = toArray(arguments, 1)
// 参数第一项,加一个Vue实例进去
args.unshift(this)
// plugin 有 install 这个方法
if (isFunction(plugin.install)) {
// 执行一下install,再把参数传递进去
plugin.install.apply(plugin, args)
} else if (isFunction(plugin)) {
// 如果plugin 本身就是函数 直接执行
plugin.apply(null, args)
}
// 用一个数组存储已经注册的插件
installedPlugins.push(plugin)
return this
}
}
javascript
// Vue.use本身就是一个函数,用来安装插件
// 1. 先判断这个插件有没有安装过, 如果安装过,return
// 2. 如果plugin没有安装过,
// 如果plugin自带install方法, 执行它
// VueRouter.install.apply(VueRouter, [vm, a, b, c])
// 如果VueRouter内部没有install,并且它VueRouter本身是一个函数,执行它
// VueRouter.apply(null, [vm, a, b, c])
// 3. 用一个数组来存已经注册过的插件
路由核心步骤
- 配置路由规则
javascript
// 创建一个路由对象
const router = new VueRouter({
// 路由的规则
// route: 一条路由规则
routes: [
{
// 路径 锚点
// 组件
path: '/find',
component: Find,
},
{
path: '/my',
component: My,
},
{
path: '/friend',
component: Friend,
},
],
})
- 指定路由出口
vue
<div class="top">
<!-- 路由的出口 -->
<router-view></router-view>
</div>
javascript
// 区分router routes route
// 1. router: 整个全局最大的路由实例,只有一个,唯一的
// 2. routes: 路由规则的列表,里面是一个数组,存了很多很多的路由规则 [{},{},{}]
// 3. route : 一条路由规则,是一个对象 {path:'', component:xx } ==> route
新建三个组件 views
路由模块封装抽离
新建router/index.js文件
javascript
import Vue from 'vue'
import VueRouter from 'vue-router'
// 1. 下载vue-touer 3.6.5
// 2. 引入VueRouter
// 3. Vue.use()
// 4. 创建router实例
// 5. 挂载到vue根实例上
// @别名 ==> 指代的是src目录,可以直接从src触发,找文件 可维护性高
import Find from '@/views/find.vue'
import My from '@/views/my.vue'
import Friend from '@/views/friend.vue'
// 在vue中,使用vue的插件,都需要调用Vue.use()
// Vue.use 可以进行插件的内部初始化 符合Vue插件的语法就需要使用
Vue.use(VueRouter)
// Vue.use本身就是一个函数,用来安装插件
// 1. 先判断这个插件有没有安装过, 如果安装过,return
// 2. 如果plugin没有安装过,
// 如果plugin自带install方法, 执行它
// VueRouter.install.apply(VueRouter, [vm, a, b, c])
// 如果VueRouter内部没有install,并且它VueRouter本身是一个函数,执行它
// VueRouter.apply(null, [vm, a, b, c])
// 3. 用一个数组来存已经注册过的插件
// 核心两个步骤
// 1. 配置路由规则
const router = new VueRouter({
routes:[
// path 指的是URL路径
{ path: '/find', component: Find}, // route ==> 一条一条的路由规则
{ path: '/my', component: My},
{ path: '/friend', component: Friend},
]
})
// 区分router routes route
// 1. router: 整个全局最大的路由实例,只有一个,唯一的
// 2. routes: 路由规则的列表,里面是一个数组,存了很多很多的路由规则 [{},{},{}]
// 3. route : 一条路由规则,是一个对象 {path:'', component:xx } ==> route
export default router
main.js导入
javascript
import Vue from 'vue'
import App from './App.vue'
// 直接导入
import router from './router'
new Vue({
render: h => h(App),
router
}).$mount('#app')
声明式导航router-link代替a标签高亮显示
vue
.router-link-active {
background-color: skyblue!important;
color: #fff!important;
}
<!-- 声明式导航 -->
<!-- 1.a ==> router-link 2. href => to属性 3. #去掉
-->
<router-link to="/find">发现音乐</router-link>
<router-link to="/my">我的音乐</router-link>
<router-link to="/friend">朋友</router-link>
router-link两个类名,精确匹配和模糊匹配
router-link类名自定义
vue
<!-- 1. 可以在router-link上自定义,优先级高 -->
<router-link
to="/find"
active-class="i-active"
exact-active-class="i-exact-active">
发现音乐
</router-link>
<router-link to="/my">我的音乐</router-link>
<router-link to="/friend">朋友</router-link>
javascript
// 2. 在创建router实例的时候,自定义类名 ~~ 全局,所有的router-link都生效
const router = new VueRouter({
// 自定义激活的类名
linkActiveClass:'my-active',
linkExactActiveClass:'my-exact-active',
routes:[
// path 指的是URL路径
{ path: '/find', component: Find}, // route ==> 一条一条的路由规则
{ path: '/my', component: My},
{ path: '/friend', component: Friend},
]
})
巩固练习
javascript
// Login Register Article List
//=> router/index.js
查询参数传参
vue
<template>
<div>
<!-- 1. 声明式导航 -->
<div class="wrap">
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<router-link to="/article?desc=美食&city=淄博">文章</router-link>
<router-link to="/list">列表</router-link>
</div>
<!-- 2.配置路由出口,挖个坑,组件会在这个位置显示 -->
<div class="main">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {};
</script>
<style scoped>
.wrap{
display: flex;
width: 400px;
margin:20px auto;
}
.wrap a{
flex: 1;
text-align: center;
}
.main{
height: 600px;
border: 1px solid red;
}
/* router-link=active 模糊匹配 to="/my" /my /my/one */
/* exact ==> 精确匹配 to="/find" */
.router-link-active{
background-color: skyblue !important;
color:#fff !important;
}
</style>
Article.vue
vue
<template>
<div>
<h2>文章页面</h2>
<p>描述:{{$route.query.desc}}</p>
<p>城市:{{$route.query.city}}</p>
<p>类型:{{$route.query.type || '暂无'}}</p>
</div>
</template>
<script>
export default {
name:'ArticleIndex',
created(){
// this.$route 当前这个路由所有相关信息
console.log(this.$route)
console.log(this.$route.query)
// URI编解码
// encodeURIComponent()
// decodeURIComponent()
// 解码
console.log(decodeURIComponent(this.$route.fullPath))
}
}
</script>
<style>
</style>
声明式导航-动态路由传参
配置动态路由
javascript
const router = new VueRouter({
routes:[
// path 指的是URL路径 ==> :id 表示 可以动态的传id, id值可变
{ path: '/user/:id', component: User},
]
})
vue
<template>
<div>
<h3>我是登录页</h3>
<!-- 声明式导航 动态路由传参 -->
<router-link to="/user/009">跳转到007用户</router-link>
</div>
</template>
<script>
export default {
name:'LoginIndex'
}
</script>
<style>
</style>
vue
<template>
<div>
我是用户页
<p>用户id:{{$route.params.id}}</p>
</div>
</template>
<script>
export default {
name:'UserIndex',
created(){
console.log(this.$route)
}
}
</script>
<style>
</style>
javascript
// 声明式导航传参小结
// 1. 查询参数模式
<router-link to="/article?desc=美食&city=淄博">文章</router-link>
// 2. 动态路由模式
// - 需要配置动态路由
<router-link to="/user/009">跳转到007用户</router-link>
// 接收:
// 查询参数 => $route.query.key
// 动态路由 => $route.params.key
编程式导航
用JS的方式实现跳转
- path路径跳转
- name命名路由跳转
javascript
// 1. path路径跳转
this.$router.push({
path:'/article'
})
// => path形式简写
this.$router.push('/article')
// 2. name属性跳转
// 2.1. 需要再router/index.js中匹配规则中写name
// 2.2
this.$router.push({
name:'list'
})
编程式导航传参
javascript
methods:{
// login页跳转到文章页,传参
goArticle(){
// this.$router.push('/article')
this.$router.push({
// 用path路径跳转
path:'/article',
query:{
desc:'好吃的',
city:'成都',
type:'火锅'
},
// path形式跳转,params会被忽略
params:{
test:1234
}
})
},
// 用name路由名的写法跳转传参,
goList(){
// 路由名字方式跳转,需要配置名字
this.$router.push({
name:'List',
// query形式的传参,会展示到url地址上
query:{
demo:666
},
// 不会展示到url上
params:{
test:1234
}
})
}
}
javascript
// query传参:参数会拼接到URL地址上,刷新不会丢失
// params传参:配合name使用
// - 不会显示到地址栏,刷新会丢失,常需要配合localStorage一起进行数据持久化处理
// 1. 不管path跳转,还是name跳转,都可以用query传参
// 2. 当不想展示参数内容,用params传参
new Vue经历了什么
javascript
// 当我们执行 new Vue()的时候,经历了哪些步骤?
// 1. core/instance/index.ts
function Vue(options){
// _init 私有 ==> 它不想让你看到
this._init(options)
}
// 2. core/instance/init.ts
Vue.prototype._init = function(){
// 初始化生命周期
// 初始化实例的属性、数据:$parent, $children, $refs, $root, _watcher...等
initLifecycle(vm)
/*初始化事件*/
initEvents(vm) // 初始化事件:$on, $off, $emit, $once
/*初始化render*/
initRender(vm) // 初始化渲染: render, mixin
callHook(vm, 'beforeCreate') // 调用生命周期钩子函数
// resolve injections before data/props
initInjections(vm) // 初始化 inject
initState(vm) // 初始化组件数据:props, data, methods, watch, computed
// resolve provide after data/props
initProvide(vm) // 初始化 provide
callHook(vm, 'created') // 调用生命周期钩子函数
}
// 3.
initState(vm) ==> if(opts.data) => initData(vm) => observe(data)
=> return new Observer() => defineReactive() => Object.defineProperty
// 按住Ctrl+点击鼠标左键,进入函数, 按住Alt 按键盘左键,返回上一层。
数据代理
javascript
let color = 'skyblue'
const obj = {
id:1,
name:'小米',
price:1999
// color
}
// 需求,给obj添加一个color属性
Object.defineProperty(obj, 'color', {
configurable:true, // 决定这个color是否可以配置或者说删除
enumerable:true, // 决定它是否可以被遍历
// value writable ==> 不能和get和set一起使用
get:function(){
return color
},
set:function(val){
color = val
}
})
// 我让obj的color属性,代理了外层的color变量
javascript
// 数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
let obj = {}
let obj2 = {
x:100,
y:100
}
// data(){
// return {
// msg:'123'
// }
// }
// data = vm._data = {msg:'123'}
// this.msg vm._data.msg vm.$data.msg
// ==> this.msg
// obj本身没有x属性
// 我想 读取obj.x 的时候,访问到obj2.x
// 设置obj.x 的时候,设置obj2.x
Object.defineProperty(obj, 'x', {
get(){
return obj2.x
},
// obj.x = '123'
set(newVal){
obj2.x = newVal
}
})
// 相当于用 obj 去代理 对 obj2中x的属性操作
javascript
let obj = {msg:'hello world'}
const vm = new Vue({
el:'#app',
data:obj,
// template:''
})
// 1.Vue中的数据代理
// 通过vm对象来代理data对象中属性的操作(读/写)
vm._data = options.data = data || {}
// vm.msg => vm._data.msg proxy方法做的代理
// 2. 数据代理的好处
// 更加方便的操作data中的数据