Skip to content

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. 用一个数组来存已经注册过的插件

路由核心步骤

  1. 配置路由规则
javascript
// 创建一个路由对象
const router = new VueRouter({
  // 路由的规则
  // route: 一条路由规则
  routes: [
    {
      // 路径 锚点
      // 组件
      path: '/find',
      component: Find,
    },
    {
      path: '/my',
      component: My,
    },
    {
      path: '/friend',
      component: Friend,
    },
  ],
})
  1. 指定路由出口
vue
<div class="top">
  <!-- 路由的出口 -->
  <router-view></router-view>
</div>
javascript
// 区分router routes route 
// 1. router: 整个全局最大的路由实例,只有一个,唯一的
// 2. routes: 路由规则的列表,里面是一个数组,存了很多很多的路由规则  [{},{},{}]
// 3. route : 一条路由规则,是一个对象  {path:'', component:xx }  ==> route

新建三个组件 views

image.pngimage.pngimage.png

路由模块封装抽离

新建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两个类名,精确匹配和模糊匹配

image.png

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的方式实现跳转

  1. path路径跳转
  2. 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中的数据