Vue基础--计算属性&侦听器&组件&插槽&自定义指令&生命周期&路由

162 阅读7分钟

计算属性 computed

计算属性: 一个特殊属性,值依赖于另外一些数据动态计算出来

注意点:

  1. 计算属性必须定义在computed节点中
  2. 计算属性必须是一个function,计算属性必须有返回值
  3. 计算属性不能被当作方法来调用,要作为属性来使用
  4. 计算属性也是属性,所以不要和data里的属性重名,用起来也和data类似

计算属性缓存特性

  • 计算属性基于依赖项的值进行缓存,依赖的变量不变,就直接从缓存中去结果,依赖的变量改变,则重新计算
  • 计算属性如果被多次使用,性能极高

简写语法

<template>
  <div>
    <p>和为:{{ getSum }}</p>
  </div>
</template>
复制代码
computed: {
    // '计算属性名'(){ return '值' }
    getSum(){
        return 100
    }
}
复制代码

计算属性的设置问题--完整写法

  1. 计算属性默认情况下只能获取,不能修改
  2. 如果需要给计算属性赋值,就必须写计算属性的完成写法!
computed: {
    getSum: {
       get(){
           ...
       },
       // value是改变的值   
       set(value){
           ...
       }
    }
}
复制代码
  1. get函数:获取计算属性的值会调用get,get会缓存,不一定每次都执行
  2. set函数:修改计算属性的时候会触发set,第一个参数就是修改的值

计算属性案例

<template>
  <div>
    全选:<input type="checkbox" v-model="isAll"> <button>反选</button>
    <ul>
      <li v-for="item in students" :key="item.name">
        <input type="checkbox" v-model="item.checked">{{ item.name }}
      </li>
    </ul>
  </div>
</template><script>
export default {
  data() {
    return {
      students: [
        {
          name: "猪八戒",
          checked: false,
        },
        {
          name: "孙悟空",
          checked: false,
        },
        {
          name: "唐僧",
          checked: false,
        },
        {
          name: "沙师弟",
          checked: false,
        },
      ]
    }
  },
  computed: {
    isAll: {
      // 读取计算属性
      get(){
        let all;  // undefined
        this.students.forEach(item => {
          // 如果有一个没有选中,那么全选就是false
          if(item.checked === false){
            all = false
          }
        });
        // 如果all还是undefined,代表所有选项都选中了
        if(all === undefined){
          return true
        }else {
          return false
        }
      },
      // 修改计算属性
      set(value){
        this.students.forEach(item => {
          item.checked = value
        })
      }
    }
  }
}
</script><style></style>
复制代码

侦听器 watch

作用:watch:可以侦听到data/computed属性值的改变

简写语法:

<template>
  <div>
    <input type="text" v-model="name">
  </div>
</template>
复制代码
watch: {
    // '被侦听的属性名'(newVal,oldVal){}
    name(newVal,oldVal){ // 当name变量的值改变触发此函数
        console.log(newVal,oldVal)
    }
}
复制代码

深度侦听和立即执行--完整写法

如果监听的是复杂数据类型,需要深度监听,需要指定deep为true, 需要用到监听的完整的写法

watch: {
    //"要侦听的属性名":{immediate:true,deep:true,handler(newVal,oldVal){}}
    student: {
        immediate: true, // 立即执行,开始监听的时候,带着当前的值触发一次handler
        deep: true, // 深度侦听复杂类型内变化
        // 当数据变化,会调用handler,他有两个参数
        // 引用类型的新值和旧值指向的都是同一个地址,所以新值和旧值相等
        handler(newVal, oldVal){
            ....
        }
    }
}
复制代码

created

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

比如 created 钩子可以用来在一个实例被创建之后执行代码:

// 组件渲染,需要先创建实例
// 组件创建后,会调用created函数
created () {
    // 在这里可以做一些数据初始化工作
    // 读取本地缓存的数据
    const locList = localStorage.getItem('list')
    // 判断本地是否有数据
    if(locList !== null){
        // 把本地存储的字符串还原成数组
        this.list = JSON.parse(locList)
    }
},
复制代码

组件

为什么使用组件

  • 提高了 复用性和灵活性
  • 提升了 开发效率 和 后期可维护性

什么是组件化开发

  • 组件是可复用的 Vue 实例, 封装标签, 样式和JS代码
  • 组件化 :封装的思想,把页面上 可重用的部分 封装为 组件,从而方便项目的 开发 和 维护
  • 一个页面, 可以拆分成一个个组件,一个组件就是一个整体
  • 每个组件可以有自己独立的 结构 样式 和 行为(html, css和js)
  • 例如:www.ibootstrap.cn/ 所展示的效果,就契合了组件化开发的思想。

组件的注册使用

App.vue 是根组件, 这个比较特殊, 是最大的一个根组件。其实里面还可以注册使用其他小组件。

使用组件的四步:

  1. 创建组件:写一个vue文件

  2. 引入组件

  3. 注册组件

    • 全局注册 – main.js中
    • 局部注册 – 某.vue文件内 – 可以注册多个组件
  4. 使用组件: 用注册的名字作为标签名,写出来

注意:组件不能和内置的html名同名

局部注册组件语法

import 组件对象 from 'vue文件路径'
export default {
    components: {
        "组件名": 组件对象
    }
}
复制代码

全局注册组件语法

import Vue from 'vue'
import 组件对象 from 'vue文件路径'Vue.component("组件名", 组件对象)
复制代码

组件名的命名规范

  • 在进行组件的注册时,定义组件名的方式有两种:
  1. 注册使用短横线命名法,例如 hm-header 和 hm-main

    • Vue.component('hm-button', HmButton)
    • 使用时 <hm-button> </hm-button>
  2. 注册使用大驼峰命名法,例如 HmHeader 和 HmMain

    • Vue.component('HmButton', HmButton)
    • 使用时 <HmButton> </HmButton><hm-button> </hm-button> 都可以

推荐1: 定义组件名时, 用大驼峰命名法, 更加方便

推荐2: 使用组件时,遵循html5规范, 小写横杠隔开(可选)

建议:组件名建议使用多个单词,用横线分隔,组件名不建议使用大写

通过 name 注册组件 (了解)

组件在 开发者工具中 显示的名字,可以通过name进行修改:在注册组件期间,除了可以直接提供组件的注册名称之外,还可以把组件的 name 属性作为注册后组件的名称

import HmButton from './components/HmButton/index.vue'
Vue.component(HmButton.name, HmButton)
// 等价于 Vue.component('HmButton', HmButton)
复制代码
export default {
    name: 'HmButton'
}
复制代码

组件样式冲突 scoped

默认情况下,写在组件中的样式会 全局生效,因此很容易造成多个组件之间的样式冲突问题。

  1. 全局样式: 默认组件中的样式会作用到全局
  2. 局部样式: 可以给组件加上 scoped 属性, 可以让样式只作用于当前组件

scoped原理?

  • (1)当前组件内标签都被添加 data-v-hash值 的属性
  • (2)css选择器都被添加 [data-v-hash值] 的属性选择器

最终效果: 必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到

组件通信

组件通信 - 父传子 - 语法

  1. 父组件通过给子组件加属性传值
  2. 子组件中, 通过props属性接收 props: [ 'data' ]

单向数据流

  • 在vue中需要遵循单向数据流原则: (从父到子的单向数据流动, 叫单向数据流)

    1. 父组件的数据变化了,会自动向下流动影响到子组件
    2. 子组件不能直接修改父组件传递过来的 props, props是只读的!

组件通信 - 子传父 - 语法

子传父是指,子组件给父组件发事件

  1. 子组件可以通过 this.$emit('事件名', 参数1, 参数2, ...) 触发事件的同时传参的

    this.$emit("update", 10)

  2. 父组件可以给子组件注册对应的自定义事件

    <com @update="fn" />

props校验

  • 说明:props 是父传子, 传递给子组件的数据, 为了提高 子组件被使用时 的稳定性, 可以进行props校验, 验证传递的数据是否符合要求

  • 默认的数组形式, 不会进行校验, 如果希望校验, 需要提供对象形式的 props

  • props提供了多种数据验证方案,例如

    • 基础的类型检查 Number
    • 多个可能的类型[String, Number]
    • 必须项校验 required: true
    • 默认值 default: 100
    • 自定义验证函数
export default {
  // 要求父组件age参数必须是数字
  // props: { 参数名: 参数类型 }
  props: {
    // 属性名是参数名,值是参数类型
    age: Number
  }
}
复制代码

v-model 语法糖

语法糖: v-model本质上是 value属性和input事件的一层包装

v-model的作用:提供数据的双向绑定

①数据发生了改变,页面会自动变 v-bind:value

②页面输入改变 , 数据会自动变化 v-on:input

1659177076469.png

v-model给组件使用

我们经常遇到一种场景:

  1. 父组件提供一个数据给子组件使用(父传子)
  2. 子组件又需要修改父组件传过来的这个数据,所以需要子传父把值传给父组件。(子传父)

这种场景可以使用v-model进行简写。

<template>
  <div>
    <good-count v-model="num"></good-count>
  </div>
</template><script>
import GoodCount from './components/good-count.vue'
export default {
  data(){
    return {
      num: 100
    }
  },
  components: {
    "good-count": GoodCount
  }
}
</script>
<style>
</style>
复制代码
<template>
  <div>
    <h3>计数:{{ value }}</h3>
    <button @click="fn">改成500</button>
  </div>
</template><script>
export default {
  props: ['value'],
  methods: {
    fn(){
      this.$emit('input', 500)
    }
  }
}
</script>
<style>
</style>
复制代码

ref 和 $refs

作用: 利用 ref 和 $refs 可以用于 获取 dom 元素, 或者组件实例

  • 获取原生DOM标签

    • 1.目标标签 – 添加 ref 属性
    • <h1 ref="myH1" id="h">ref/id获取原生dom</h1>
      复制代码
      
    • 2.恰当时机, 通过 this.$refs.xxx, 获取目标标签
    • console.log(this.$refs.myH1)
      复制代码
      
  • 通过ref属性获取组件对象

  • 1.给Demo组件目标组件, 添加ref属性-名字随意

  • <Demo ref="de"></Demo>
    复制代码
    
    • 2.恰当时机, 通过 this.$refs.xxx 获取组件对象, 可调用组件对象里方法等
  • this.$refs.de.fn()
    复制代码
    

$nextTick 的使用

需求:点击改data的数据, 获取原生DOM内容

  1. 创建标签显示数据

    <p ref="a">数字:{{ count }}</p>
    <button>点击+1</button>
    复制代码
    
  2. 点击+1, 马上获取原生DOM内容 (拿到的是更新前的dom?)

    methods: {
        btn() {
            this.count++;
            console.log(this.$refs.a.innerHTML)
        }
    }
    复制代码
    

原因: Vue更新DOM是异步的,如果想要获取DOM更新后的内容,需要使用$nextTick

$nextTick等DOM更新后, 才会触发执行此方法里的函数体

  • 语法:this.$nextTick(函数体)
  • methods: {
        btn() {
            this.count++;
            this.$nextTick(() => {
                console.log("DOM更新后触发$nextTick函数");
                console.log(this.$refs.a.innerHTML)
            })
        }
    }
    复制代码
    

获取DOM案例

<template>
  <div>
    <button @click="replay">回复</button>
    <br>
    <input type="text" placeholder="请输入评论" v-if="showInput" ref="comment">
  </div>
</template><script>
export default {
  data(){
    return {
      showInput: false      
    }
  },
  methods: {
    replay(){
      this.showInput = true
      // 获取input的dom,获取焦点
      // $nextTick
      this.$nextTick(() => {
        // input.focus是获取焦点
        // this.$refs.comment可以获取到指定了ref的comment名字的DOM元素
        this.$refs.comment.focus()
      })
    }
  }
}
</script>
<style>
</style>
复制代码

dynamic 动态组件

动态组件是什么?

  • 是 可以改变 的 组件

动态组件能解决什么需求呢 ?

  • 解决多组件同一位置, 切换显示的需求

基本语法:

  1. component 组件(位置) + is 属性 (哪个组件)

    • <component :is="变量"> //是组件名,字符串,当你需要切换组件,就修改变量成对应的组件名
      复制代码
      
  2. 修改 is 属性绑定的值 => 切换组件

dynamic 动态组件- 怎么用(案例)

  1. 准备被切换的 2个组件, 并引入注册
  2. 准备变量来承载要显示的"组件名"
  3. 设置挂载点, is属性设置要显示的组件 ( component + is )
  4. 点击按钮 – 修改comName变量里的"组件名" ( 修改 is 的值)
<template>
  <div>
    <button @click="comName = 'little-red'">小红</button>
    <button @click="comName = 'little-blue'">小蓝</button>
    <button @click="comName = 'little-white'">小白</button>
    <component :is="comName"></component>
  </div>
</template><script>
import LittleRed from './components/little-red.vue'
import LittleBlue from './components/little-blue.vue'
import LittleWhite from './components/little-white.vue'
export default {
  data(){
    return {
      comName: 'little-red'
    }
  },
  components: {
    'little-red': LittleRed,
    'little-blue': LittleBlue,
    'little-white': LittleWhite
  }
}
</script>
<style>
</style>
复制代码

插槽

作用:组件部分内容允许调用者动态传入

1.插槽 - 默认插槽

插槽基本语法:

  1. 组件内用占位
  2. 使用组件时夹着的地方, 传入标签替换slot

1659180045705.png

1659180079122.png

2.插槽 - 后备内容(默认值)

插槽后备内容:封装组件时,可以为预留的 <slot> 插槽提供后备内容(默认内容)。

  • 语法: 在标签内放置内容, 作为默认显示内容

  • 效果:

    • 外部使用组件时,不传东西,则slot会显示后备内容 (slot标签内的结构)
    • 外部使用组件时,传东西了,则slot整体会被换掉

1659180159450.png

3.插槽 - 具名插槽

需求:一个组件内有多处,需要外部传入标签,进行定制

  • 语法:

    • 1.多个slot使用name属性区分名字
    • 2.template配合v-slot:名字来分发对应标签
    • v-slot:可以简化成#

1659180444242.png

1659180465191.png

4.插槽 - 作用域插槽

作用域插槽: 定义 slot 插槽的同时, 是可以传值的。给插槽上可以绑定数据,将来使用组件时可以用。

基本使用步骤:

  1. 给 slot 标签, 以 添加属性的方式传值

1659180543405.png

  1. 所有添加的属性, 都会被收集到一个对象中

1659180566765.png

  1. 在template中, 通过 v-slot:插槽名= "obj" 接收

1659180588940.png

自定义指令

自定义指令:自己定义指令, 封装dom操作,扩展额外功能

  • 全局注册 - 语法 - 在main.js中注册
// 全局注册自定义指令
Vue.directive("指令名",{
  inserted(el){
    // 可以对el标签扩展额外功能
  }
})
复制代码
  • 局部注册 - 语法 - 在App.vue中注册
export default {
  directives: {
    "指令名": { 
      inserted(el){
        // 对el进行操作
      }
    }
  }
};
复制代码
  • 自定义指令 - 指令的值

    • 需求:定义color指令-传入一个颜色, 给标签设置文字颜色
    • 语法:在绑定指令时,可以通过“等号”的形式为指令绑定具体的参数值
    • <template>
        <div>
          <h3 v-color>Hello, World</h3>
          <h3 v-color="textColor">Hello, World</h3>
          <button @click="textColor = 'purple'">变变变</button>
          <h3 v-color="pink">Hello, World</h3>
      ​
          <h3 v-bigger>大字体</h3>
        </div>
      </template><script>
      export default {
        data() {
          return {
            textColor: 'green',
            pink: 'pink'
          };
        },
        directives: {
          bigger: {
            inserted(el){
              el.style.fontSize = '50px'
            }
          }
        }
      };
      </script>
      复制代码
      
    • 通过 binding.value 可以拿到指令值,指令值修改会触发 update 函数。
    • // 全局注册自定义指令
      Vue.directive("color",{
        // inserted是指令所在的标签被插入到父节点之后触发
        // 在inserted里,可以拿到指令所在标签的DOM
        inserted(el,binding){
          console.log('dom', el)
          // binding有个属性value,value就是指令传的值
          el.style.color = binding.value || 'red'
        },
        // update会在指令的值变化的时候触发
        update (el, binding) {
          // 当变量变化,再修改一下颜色
          el.style.color = binding.value
        }
      })
      复制代码
      

生命周期

生命周期基本认知

vue组件生命周期:从创建 到 销毁 的整个过程就是 – Vue实例的 - 生命周期

生命周期-钩子函数概述

生命周期函数:是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行。

  • 作用: 特定的时间点,执行特定的操作

  • 比如: 组件创建完毕后,可以在created 生命周期函数中发起Ajax 请求,从而初始化 data 数据

  • 分类: 三大阶段,8个方法

    • 组件初始化阶段的生命周期函数
    • 组件运行阶段的生命周期函数
    • 组件销毁阶段的生命周期函数

生命周期钩子-详解

八大生命周期钩子函数:

  1. beforeCreate:data数据初始化之前,组件还没有数据
  2. created: data数据初始化之后,可以获取到组件的数据
  3. beforeMount:DOM渲染之前,DOM还没渲染
  4. mounted:DOM渲染之后,可以操作DOM了
  5. beforeUpdate: 数据更新,DOM更新前
  6. updated: 数据更新,DOM更新后
  7. beforeDestroy: 组件销毁前
  8. destroyed: 组件销毁后

路由基础

单页应用程序: SPA - Single Page Application

  • 单页面应用(SPA): 所有功能在一个html页面上实现 (多页面应用程序MPA)

  • 优点:

    • 不整个刷新页面,每次请求仅获取需要的部分,用户体验更好
    • 数据传递容易, 开发效率高
  • 缺点:

    • 开发成本高(需要学习专门知识 - 路由)
    • 首次加载会比较慢一点。不利于seo

客户端路由

  • 浏览器端实现页面切换
  • 路由是路径和页面组件的对应关系

Vue的路由:vue-router

vue-router: vue-router本质是 vue 官方的一个路由插件,是一个第三方包

  • 官网: router.vuejs.org/zh/
  • lvue-router集成了 路径 和 组件的切换匹配处理,我们只需要配置规则即可。

组件分类: .vue文件分2类, 一个是页面组件, 一个是复用组件

  • vue文件本质无区别, 方便大家学习和理解, 总结的一个经验

  • src/views文件夹

    • 页面组件 - 页面展示 - 配合路由用
  • src/components文件夹

    • 复用组件 - 展示数据 - 常用于复用

vue-router的基本使用(5 + 2)

  • Vue2使用3.x的路由版本

  • Vue3使用4.x的路由版本

  • 5 个 基础步骤

    • 下载vue-router模块到当前工程,版本3.5.3

      • npm i vue-router@3
    • 在main.js中引入VueRouter函数

      • import VueRouter from 'vue-router'
    • 添加到Vue.use()身上 – 帮你注册全局RouterLink和RouterView组件

      • Vue.use(VueRouter)
    • 创建路由对象

      • { routes: [{path:'路径', component: 组件变量}] }
    • 将路由对象注入到new Vue实例中

      • new Vue({ router })
  • 2 个 核心步骤:

    • 配置路由规则
    • 指定路由出口 router-view
  • 配置路由页面放在哪里

    • App.vue-> router-view

路由模块在企业开发中一般抽离成单独的模块

  • 在src目录下新建router文件目录,并在改目录下新建index.js文件,在index.js文件中配置,src/router/ -----> index.js
  • 好处:拆分模块,利于维护

声明式导航 - 导航链接

  • 组件router-link 替代 a标签,能跳转,能高亮

    • 1.vue-router提供了一个全局组件 router-link
    • 2.router-link实质上最终会渲染成a链接 to属性等价于提供 href属性(to无需#)
    • 3.router-link提供了声明式导航高亮的功能(自带类名)
<template>
  <div>
    <!-- router-link跳转页面,如果携带参数,to可以绑定 -->
    <!-- to对象有两个属性:path,跳转的路径;query属性 -->
    <router-link :to="'/foo'">Foo</router-link>
    |
    <router-link :to="`/bar">Bar</router-link>
    <router-view></router-view>
  </div>
</template>
复制代码

声明式导航 - 两个类名

  • 你在哪个页面,那个页面的router-link会有两个类

  • lrouter-link-active: 激活的导航链接 模糊匹配

    • to="/my" 可以匹配 /my /my/a /my/b ....
  • lrouter-link-exact-active: 激活的导航链接 精确匹配

  • to="/my" 仅可以匹配 /my

  • 可以修改默认高亮的类名

  • const router = new VueRouter({
        linkActiveClass: 'aa',
        linkExactActiveClass: 'aa',
        // route: 一条规则
    })
    复制代码
    

声明式导航 - 跳转传参

  • query

    • 问号后面的参数 /foo?age=18

    • :to="{ path: "路径", query: {参数名: 参数值} }"

    • 接收:this.$route

      • this.$route代表当前的路由信息
      • this.$route.query接收query参数
  • params

    • 内嵌在地址里的参数 /foo/123

    • 使用

      • 1.路由配置声明参数 /foo/:id
      • 2.跳转的时候传递参数 <router-link :to="/foo/${id}"
      • 3.接收参数 this.$route.params.id
  • 代码演示

// 主组件App.vue
<template>
  <div>
    <!-- router-link跳转页面,如果携带参数,to可以绑定 -->
    <!-- to对象有两个属性:path,跳转的路径;query属性 -->
    <router-link :to="{ path: '/foo', query: { name: 'xuee', age: 18 } }">Foo</router-link>
    |
    <router-link :to="`/bar/${productId}`">Bar</router-link>
    <router-view></router-view>
  </div>
</template><script>
export default {
  data(){
    return {
      productId: 666
    }
  }
}
</script><style scoped>
  .router-link-active {
    color: red;
  }
</style>
复制代码
// 子组件 bar.vue
<template>
  <div>
    这是bar组件
  </div>
</template><script>
export default {
  created(){
    console.log(this.$route);
    console.log(this.$route.params);
    console.log(this.$route.params.id);
  }
}
</script><style></style>
复制代码
// 子组件 foo.vue
<template>
  <div>
    这是foo组件
  </div>
</template><script>
export default {
  created () {
    console.log(this.$route);
    console.log(this.$route.query.name);
    console.log(this.$route.query.age);
  }
}
</script><style></style>
复制代码

vue路由 - 重定向

重定向:匹配path后, 强制跳转path路径

  • 网页打开url默认hash值是/路径
  • redirect是设置要重定向到哪个路由路径
// new一个VueRouter
const router = new VueRouter({
  // routes代表路由配置
  routes: [
    {
      path: "/", // 匹配的路径
      redirect: "/foo", // 匹配到上面的路径后重定向到这个路径
    },
    {
      path: "/foo",
      component: Foo,
    },
    {
      path: "/bar/:id",
      component: Bar,
    }
  ],
});
复制代码

vue路由 - 404

  • 404:当找不到路径匹配时,给个提示页面
  • 路由最后, path匹配*(任意路径) – 前面不匹配就命中最后这个
import NotFound from '../views/NotFound.vue'
// new一个VueRouter
const router = new VueRouter({
  // routes代表路由配置
  routes: [
    {
      path: "/", // 匹配的路径
      redirect: "/foo", // 匹配到上面的路径后重定向到这个路径
    },
    {
      path: "/foo",
      component: Foo,
    },
    {
      path: "/bar/:id",
      component: Bar,
    },
    {
      path: '*',
      component: NotFound,
    }
  ],
});
复制代码

vue路由 - 模式设置 - 修改路由,在地址栏的模式

const router = new VueRouter({
    routes,
    mode: "history"
})
复制代码

编程式导航 - 基本跳转

编程式导航:用JS代码来进行跳转

  • 语法: path或者name任选一个
// html标签中写法
<button @click="$router.push({ path: '/foo'})">Foo</button>
复制代码
// script中写法
methods: {
    fn(){
        this.$router.push({
            path: "/foo"
        })
    }
}
复制代码

1659358560589.png

编程式导航 - 路由传参

  • 语法: query或params都可以传参

1659358639261.png

query传:$route.query.xxx 接收

params传:$route.params.xxx 接收

区别:

  • params传参:是在内存中传参,刷新会丢失
  • query传参:是在地址栏传参,刷新还在

注意: 使用path会忽略params

1659429379635.png

<template>
  <div>
    <!-- router-link跳转页面,如果携带参数,to可以绑定 -->
    <!-- to对象有两个属性:path,跳转的路径;query属性 -->
    <router-link :to="{ path: '/foo', query: { name: 'xuee', age: 18 } }">Foo</router-link>
    |
    <router-link :to="`/bar/${productId}`">Bar</router-link>
    <br>
    <!-- <button @click="$router.push('/foo')">Foo</button> -->
    <button @click="$router.push({ path: '/foo', query: { age: 18 } })">Foo</button>
    <!-- <button @click="$router.push(`/bar/${productId}`)">Bar</button> -->
    <!-- path和params不能一起使用,params要和name属性搭配使用 -->
    <button @click="$router.push({name: 'xxx', params: { id: 123 } })">Bar</button>
    <router-view></router-view>
  </div>
</template><script>
export default {
  data(){
    return {
      productId: 666
    }
  }
}
</script><style scoped>
  .router-link-active {
    color: red;
  }
</style>
复制代码
// 引入VueRouter函数
import VueRouter from "vue-router";
import Vue from "vue";
import Foo from "../views/foo.vue";
import Bar from "../views/bar.vue";
import NotFound from '../views/NotFound.vue'// 注册VueRouter的功能
Vue.use(VueRouter);
​
// new一个VueRouter
const router = new VueRouter({
  // routes代表路由配置
  routes: [
    {
      path: "/", // 匹配的路径
      redirect: "/foo", // 匹配到上面的路径后重定向到这个路径
    },
    {
      path: "/foo",
      component: Foo,
    },
    {
      name: 'xxx',
      path: "/bar/:id",
      component: Bar,
    },
    {
      path: '*',
      component: NotFound,
    }
  ],
});
​
// 导出router对象
export default router;


作者:Hsu_Ee
链接:juejin.cn/post/713173… 来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。