vue基础知识(一)

Vue: 用于构建用户界面的渐进式框架。包含声明式渲染、组件系统、客户端路由、大规模状态管理、构建工具。

Vue官网地址:vue2 介绍 — Vue.js

                        Vue3 介绍 — Vue.jsVue.js - 渐进式 JavaScript 框架 | Vue.js

1. 创建一个Vue实例

设置容器----引入Vue.js----创建Vue实例-----添加配置

<!-- 设置容器 -->
<div id="app">
    {{ msg }}  <!-- 插值表达式 渲染页面页面-->
</div>
<script src="vue.js"></script>
<script>
    //创建Vue实例
    const app = new Vue({
        el: '#app', //挂载容器
        //声明数据
        data: {     
            msg: 'Hello World!'
        }
    })
</script>

2. 插值表达式

语法格式 {{ 表达式 }}。可以动态响应式渲染页面。

表达式使用js语法进行解析,不能包含条件或逻辑判断语句如:if,表达式中引用的变量必须在Vue实例data中声明。

3. Vue指令介绍

1).  v-html:

解析Html标签

<div v-html="html"></div>

2).  v-show:

控制元素的显隐性,其实现原理是通过控制css的display属性控制元素是否显示。适用于显隐性变化频繁的场景。

3).  v-if:

条件渲染,其原理是通过表达式值,判断是否添加或移除dom元素。

<div v-show="Math.random() > 0.5">
  Now you see me show
</div>
<div v-if="Math.random() > 0.5">
  Now you see me if
</div>
<div v-else>
  Now you don't
</div>

v-else: 配合v-if使用,不需要表达式

v-else-if: 配合v-if使用

4).  v-on:

绑定事件,通过方法或内联语句绑定,可以缩写为@

  • 修饰符

    • .stop - 调用 event.stopPropagation(),阻止冒泡。eg:存在包含行为,只执行最上层行为。
    • .prevent - 调用 event.preventDefault(),阻止默认行为。eg:链接不跳转
    • .capture - 添加事件侦听器时使用 capture 模式。
    • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
    • .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调,@keyup.enter监听回车按键。
    • .native - 监听组件根元素的原生事件。
    • .once - (2.1.4) 只触发一次回调。
    • .left - (2.2.0) 只当点击鼠标左键时触发。
    • .right - (2.2.0) 只当点击鼠标右键时触发。
    • .middle - (2.2.0) 只当点击鼠标中键时触发。
    • .passive - (2.3.0) 以 { passive: true } 模式添加侦听器
<!-- 只点击一次 -->
<button v-on:click.once="warn('Form cannot be submitted yet.', $event)">
   Submit
</button>

 5).  v-bind:

绑定数据到属性或组件,可以缩写为:

可以动态控制class,用于标签高亮切换等

<div :class="{ css属性名:boolean, css属性名2:boolean }"></div>
<div :class="[ css属性名, css属性名2 ]"></div>

 也可以与style合用,数据驱动设置样式动态变化,例如:进度条,行内样式增强

<div :style="{ css属性名:属性值, css属性名2:属性值 }"></div>

6).  v-for:

基于数据循环,可以多次渲染整个元素。当和 v-if 一起使用时,v-for 的优先级比 v-if 更高。:key属性,列表元素的唯一标识,将数据和元素作为一个整体一起修改。key的值只能是字符串或数字,唯一

<div v-for="(item, index) in items" :key="item.id"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, name, index) in object"></div>

7).  v-model:

本质是语法糖。实现数据和视图的双向绑定,用于表单,可以获取或设置form元素的内容。 

  • 修饰符

    • .lazy - 取代 input 监听 change 事件
    • .number - 输入字符串转为有效的数字 
    • .trim - 输入首尾空格过滤

 利用语法糖原理,在自定义组件中使用v-model,代替原有值和默认事件。当子组件接收父组件值,使用value时,可以不适用model属性,否则必须加model声明

a99fdc31aec64cadbdcaefdba32089b8.png

自定义组件中的值传递,也可以使用.sync实现

父组件  

<SonA :pData.sync="pData"></SonA>

 子组件

<template>
    <div>
        我是子组件A ,测试v-model语法糖
        <input :value="pData" @input="changeFatherValue"/>
    </div>
</template>
<script>
export default {
    //props:['pData']
    props: {
        pData:{
            type: String
        }
    },
    methods:{
        changeFatherValue(e){
            this.$emit('update:pData', e.target.value);//必须使用 update
        }
    }
}
</script>

8)自定义指令 directive/directives

 封装一些对dom元素的操作。自定义指令中的钩子有bind、inserted、update、unbind、componentUpdated

<span v-color='colorD'>测试全局指令</span>

//全局自定义指令,focus是自定义的指令名,binding.value可以获取自定义指令的值
Vue.directive('color', {
  //组件加载时调用
  inserted(el, binding){
    el.style.color=binding.value
  },
  //指令绑定数据时调用
  update(el, binding){
    el.style.color=binding.value;
  },
})

//局部自定义指令
directives: {
    color: {
      //组件加载时调用
      inserted(el, binding) {
        el.style.color = binding.value
      },
      //指令绑定数据时调用
      update(el, binding) {
        el.style.color = binding.value;
      },
    }
  }

 4. 选项/数据

1). computed

计算属性,基于现有数据,自动计算其他属性,会自动变化,同时可以设置get\set方法,使用的时候计算属性中的方法名作为普通属性使用。

<div id="app">
    <div>总数为:{{ total }}</div>
</div>

<script src="vue.js"></script>
<script>
    //创建Vue实例
    const app = new Vue({
        el: '#app', //挂载容器
        //声明数据
        data: {
            alist: [{"id": 1,"num": 2},{"id": 2,"num": 5},{"id": 3,"num": 8}],
        },
        computed: {
            total: function(){
                return this.alist.reduce((sum, item)=> sum + item.num, 0);
            },
            // 读取和设置
            aPlus: {
                get: function () {
                    return this.a + 1
                },
                set: function (v) {
                    this.a = v - 1
                }
            }

        },
    })
</script>

    计算属性相较于method,具有缓存特性,对于同一属性,多副本使用的情况,计算属性只执行一次,可以有效提高性能。

2). watch

监听数据变化,数据变化后执行函数或方法。

<div id="app">
    测试watch监听<textarea v-model="obj.info"></textarea>
    <button @click="addObj">添加对象属性</button>
</div>
<script>
    //创建Vue实例
    const app = new Vue({
        el: '#app', //挂载容器
        //声明数据
        data: {
            obj: {
                info: ""
            },
        },
        methods: {
            addObj: function () {
                this.obj.newP= '333';//无法监听到新增属性
                this.$set(this.obj,"newP",5555);//可以监听到新增属性
            }
        },
        watch: {
            //防抖设置
            'obj.info'(newValue, oldValue) {
                clearTimeout(this.timer);
                this.timer = setTimeout(() => {
                    console.info(newValue + '<----' + oldValue);
                }, 1000);
            },
            obj: {
                deep: true, //监听复杂对象,深度
                immediate: true, //在监听开始执行一次
                handler: function (newValue, oldValue) { //oldValue与newValue值相同 
                    clearTimeout(this.timer);
                    this.timer = setTimeout(() => {
                        console.info(JSON.stringify(newValue) +'----'+ JSON.stringify(oldValue));
                    }, 1000);
                }
            }
        }
    })
</script>

         watch监听复杂对象,对于新加入的属性,

如果使用this.objectName.propertyName=value方式无法进行监听;原因是vue在初始化的时候,会对复杂对象中的每一个属性设置get\set监听,所以新增属性无法检测到

如果使用this.$set(this.objectName,"propertyName",value)方式可以进行监听;

watch监听复杂对象时handler方法中,无法获取的变化前的值。

3) data

Vue 实例的数据对象。Vue 会递归地把 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。对象必须是纯粹的对象 (含有零个或多个的 key/value 对):浏览器 API 创建的原生对象,原型上的 property 会被忽略。大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。

data在组件中必须是一个函数,通过return返回数据,保证每一个组件实例,维护独立的一份数据对象。


<script>
    //创建Vue实例
    const app = new Vue({
        el: '#app', //挂载容器
        //声明数据
        data: {
            obj: {
                info: ""
            },
        },
        //组件中写法
        data() {
            retutn {
                obj: {
                    info: ""
                },
            }
        },
    })
</script>

5. Vue的生命周期

Vue实例从创建到销毁的过程,分为四个阶段:创建(生成响应式数据data)、挂载(渲染模板)、更新(更新视图,修改数据)、销毁(销毁实例)

钩子函数:在Vue的生命周期周,提供给开发人员,运行业务代码的方法。包含:

  • beforeCreate(实例初始化之后,进行数据侦听和事件/侦听器的配置之前。响应式数据准备好之前,无法获取到data数据);
  • created(响应式数据准备好之前,可以获取到data数据。在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数);
  • beforeMount(模板渲染之前,无法获取到dom);
  • mounted(模板渲染之后,可以获取到dom);

   mounted 不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作,可以在 mounted 内部使用 vm.$nextTick

mounted: function () {
  this.$nextTick(function () {
    // 仅在整个视图都被渲染之后才会运行的代码
  })
}
  • beforeUpdate(数据修改后,dom渲染前,获取到修改后的数据,修改前的dom);
  • updated(dom渲染后,获取到修改后的数据,修改后的dom);
  • beforeDestroy(卸载前,切除vue以外的资源调用);
  • destroyed(卸载后);app.$destroy()

6. Vue脚手架安装与使用

1). 安装vue-cli,执行yarn global add @vue/cli 或者 npm i @vue/cli

PS C:\Users\******> npm i @vue/cli -g
npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
npm WARN deprecated source-map-url@0.4.1: See https://github.com/lydell/source-map-url#deprecated
......
npm WARN deprecated subscriptions-transport-ws@0.11.0: The `subscriptions-transport-ws` package is no longer maintained. We recommend you use `graphql-ws` instead. For help migrating Apollo software to `graphql-ws`, see https://www.apollographql.com/docs/apollo-server/data/subscriptions/#switching-from-subscriptions-transport-ws    For general help using `graphql-ws`, see https://github.com/enisdenjo/graphql-ws/blob/master/README.md
npm WARN deprecated shortid@2.2.16: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

added 855 packages in 3m
PS C:\Users\*******>

2). 查看vue版本 vue --version

3). 创建项目  vue create 项目名(项目名不能使用中文)

D:\workspace\learn>vue create vue-demo


Vue CLI v5.0.8
? Please pick a preset: Default ([Vue 2] babel, eslint)


Vue CLI v5.0.8
✨  Creating project in D:\workspace\learn\vue-demo.
🗃  Initializing git repository...
⚙️  Installing CLI plugins. This might take a while...

npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.

added 866 packages in 3m
🚀  Invoking generators...
📦  Installing additional dependencies...

npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.

added 94 packages in 2m
⚓  Running completion hooks...

📄  Generating README.md...

🎉  Successfully created project vue-demo.
👉  Get started with the following commands:

 $ cd vue-demo
 $ npm run serve

 WARN  Skipped git commit due to missing username and email in git config, or failed to sign commit.
       You will need to perform the initial commit yourself.


D:\workspace\learn>

4). 启动项目 yarn serve或npm run servr(package.json中的名称)

D:\workspace\learn\vue-demo>npm run serve
npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.

> vue-demo@0.1.0 serve
> vue-cli-service serve

 INFO  Starting development server...


 DONE  Compiled successfully in 3746ms                                                                          15:38:18

  App running at:
  - Local:   http://localhost:8080/
  - Network: http://***.***.***.***:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

7. Vue组件

1). 组件组成成分

组件由三部分组成,分别是结构(template)、样式(style)、行为(script)

注意:

1. 结构只能有一个,<template>里只能有最外层的<div>只能有一个

2.样式默认是全局的,局部样式需要增加scoped,只作用于当前组件。

        例如:<style scoped></style>

        scoped原理是:给当前组件模板的所有元素增加一个自定义属性,以data-v-hash值作为div样式选择器,可以使用data-v-hash区分你不同的组件。

2). 组件间传值

    1. 父组件传值到子组件props

         父组件调用子组件时,将要传递的数据注册到子组件的标签里,子组件使用props接收父组件转过来的值。props可以对接收的值设置数据类型、是否非空、默认值、自定义校验方法。

73d8f3b8613548cf9c2c25bca4a2d3d8.png

    props复杂校验

<script>
export default {
    //props:['pData']
    props: {
        pData: String,
        jsonData: {
            type: Object,//数据类型
            default: ()=> {},//默认值
            required: true,//非空
            validator(val){     //自定义校验方法
                if(val.info==1){
                    return false;
                }else{
                    return true;
                }
            }
        }
    }
}
</script>

 tips:props使用时遵循单项数据流原则,在子组件中不建议直接修改。

    2. 子组件传值到父组件

        子组件传值到父组件,子组件使用vm.$emit注册事件,父组件监听事件,调用方法获取子组件返回的数据并处理。

<!-- 父组件 -->
<template>
  <div id="app">
    <SonC @eventName1="receiveSonData"></SonC>
  </div>
</template>

<script>
import SonC from './components/SonC.vue'

export default {
  name: 'App',
  components: {
    SonC
  },
  methods:{
    receiveSonData(val, val2){
      alert(val + "----" + val2);
    }
  }
}
</script>

<!--  子组件  -->
<template>
    <div>
        <button @click="trsData">调用父组件</button>
    </div>
</template>
<script>
export default {
    data(){
        return {
            sonData:22223,
            sonData2:33333
        }
    },
    methods:{
        trsData(){
            this.$emit("eventName1", this.sonData, this.sonData2);//事件名,参数1,参数2..
        }
    }
}
</script>

参数值可以输多个,监听事件名与注册事件名保持一致

3. 非父子组件间传值 --事件总线(event bus)

        适用于简易消息处理。类似于观察者模式。

        实现步骤:

        1.创建Bus总线实例,Bus实例区别与原有的项目实例,独立存在;

        2.在接受消息的组件中引入Bus,在vue实例created中使用$on接收消息;

        3.在发送消息组件中使用$emit触发事件。

<!-- 主页面 -->
<template>
  <div id="app">
    <ComA></ComA>
    <ComB></ComB>
    <SendMsgC></SendMsgC>
  </div>
</template>

<script>
import ComA from './components/ComA.vue';
import ComB from './components/ComB.vue';
import SendMsgC from './components/SendMsgC.vue';

export default {
  name: 'App',
  components: {
    SendMsgC,
    ComA,
    ComB
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


<!-- 发送消息组件  -->
<template>
    <div>
        <button @click="sendMsgs">发送消息</button>
    </div>
</template>

<script>
import eventBus from '@/utils/eventBus.js';
export default {
    methods:{
        //发送消息
        sendMsgs(){
            eventBus.$emit("event1",2222, 444);
            console.info("wwwwww");
        }
    }
}
</script>


<!-- 接受消息组件A -->
<template>
    <div>
        接收A {{ msg }}
    </div>
</template>

<script>
import eventBus from '@/utils/eventBus.js';
export default {
    data(){
        return {
            msg:""
        }
    },
    created() {
        eventBus.$on('event1', (msg1,msg2)=>{
            this.msg = (msg1+"===="+msg2);
        })
    }
}
</script>


<!-- 接受消息组件B -->
<template>
    <div>
       接收B {{ msg }}
    </div>
</template>

<script>
import eventBus from '@/utils/eventBus.js';
export default {
    data(){
        return {
            msg:""
        }
    },
    created(){
        eventBus.$on('event1', (msg1,msg2)=>{
            this.showMsg(msg1,msg2)
        });
    },
    methods:{
        showMsg(msg1,msg2){
            console.info("ssss");
            this.msg = (msg1+"===="+msg2);
        }
    }
}
</script>

注意:发送消息和接收消息要在同一个事件总线的vue实例里,不要使用this。

4. 非父子组件间传值(跨层级 provide & inject)

    跨层级共享数据。顶层组件使用provide函数设置共享数据,子孙组件使用inject接收数据。

<!-- 顶层组件 -->
<template>
  <div id="app">
    <button @click="changeTopData">修改顶层组件数据</button>
  </div>
</template>

<script>
import ComA from './components/ComA.vue';

export default {
  name: 'App',
  components: {
    ComA
  },
  provide(){
    return {
      pData: this.pData,
      jsonData: this.jsonData
    }
  },
  data(){
    return {
      pData:"222222",
      jsonData: {
        info: 2
      },
    }
  },
  methods:{
    changeTopData(){
      this.pData = 'AAAAAAA';
      // this.$set(this.jsonData, 'newKey', 'CCCCCC');
      this.jsonData.hj='sssss';
      // this.jsonData.info = 'YYYYYY';
    }
  }
}
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


<!-- 中间层 -->
<template>
    <div>
        <LowerVue></LowerVue>
    </div>
</template>

<script>
import LowerVue from './LowerVue.vue';
export default {
    components:{
    LowerVue }
}
</script>

<!-- 底层 -->
<template>
    <div>
        孙子组件接受数据 {{ pData + '------' + JSON.stringify(jsonData) }}
    </div>
</template>

<script>
export default {
    // inject: ['pData','jsonData','uuu']
    inject:{
        pData:{
            default: ""
        },
        jsonData:{
            from: 'jsonData',
            default: ()=>{}
        },
        hj:{
            from: 'jsonData',//从其他名字的属性注入
            default: ()=>{} //设置默认值
        }
    }
}
</script>

注意:简单类型数据使用provide/inject传值时,是非响应式数据,顶层组件中数据修改后,子孙组件不会自动变化。复杂类型数据传输时,是响应式数据(其中使用this.jsonData.hj='sssss'方式增加新的属性时,vue实例无法监听到)。

5. 使用vuex共享数据

vuex使用说明:Vuex基础知识-CSDN博客

6. 其他ref & $ref  、$nextTick

1). ref & $ref

ref定义组件标识,$ref获取组件,this.$ref.组件ref.data(method)调用组件中的数据或方法。通常配合$nextTick()使用,$nextTick作用将回调延迟到下次 DOM 更新循环之后执行。

<template>
  <div id="app">
    <SendMsgC ref="sendMsg"></SendMsgC>
    <button @click="ac">触发子组件方法</button>
  </div>
</template>

<script>
import SendMsgC from './components/SendMsgC.vue';

export default {
  name: 'App',
  components: {
    SendMsgC
  },
  methods:{
    ac(){
      this.$nextTick(()=>{
        this.$refs.sendMsg.sendMsgs();
      });
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

 3). 插槽slot

插槽,使组件中的结构可以进行自定义,在组件中使用<slot></slot>占位自定义内容。使用组件时,组件的起始标签和结束标签之间的内容会替换插槽。组件中<slot></slot>标签中的内容时后备内容,可以作为组件插槽的默认值。

1. 默认插槽

只有一个slot标签

<template>
    <div>
        <div>我是插槽组件头部</div>
        <slot>我是后备内容</slot> <!-- 组件的slot默认值 -->
        <div>我是插槽组件尾部</div>
    </div>
</template>


<SlotV>第一个插槽<span v-color='colorD'>测试全局指令</span></SlotV>
<SlotV>第二个插槽<button @click="changeColor">修改指令颜色</button></SlotV>
<SlotV></SlotV>

2. 具名插槽

一个组件中有多个插槽时,需要使用name属性标识具体的插槽,使用时v-slot:插槽名。调用具名插槽组件时,需要分发给各个插槽的内容需要使<templete>包裹分发内容。v-slot:插槽名可以缩写为#。

<template>
    <div>
        <slot name="header">我是插槽组件头部</slot>
        <slot name="body">我是后备内容</slot> <!-- 组件的slot默认值 -->
        <slot name="footer">我是插槽组件尾部</slot>
    </div>
</template>

<SlotV>
      <template v-slot:header><span v-color='colorD'>测试全局指令</span></template>
      <template v-slot:body><button @click="changeColor">修改指令颜色</button></template>
      <template #footer><span v-color='colorD'>第一个插槽尾部</span></template>
    </SlotV>

3. 插槽的作用域

 父组件访问插槽组件中的数据,在插槽组件中,以添加属性的方式将数据注册到slot标签上,并将slot标签上注册的所有属性组成为一个对象。

父组件调用的时候,对于默认插槽可以直接使用#default=“接受对象变量名”接收数据;对于具名插槽需使用v-slot:插槽名=“接受对象变量名”接收数据。

父组件接收数据时,也可以对子组件传过来的数据对象进行解构,直接使用对象中的属性名接收特定数据,例如:v-slot:插槽名=“{ 插槽组件对象属性名 }”

<SlotV>
      <template v-slot:header="vdata1"><span v-color='colorD'>测试全局指令{{ vdata1 }}</span></template>
      <template v-slot:body="{ mvalue }"><button @click="changeColor">修改指令颜色{{ mvalue }}</button></template>
      <template #footer="vdata3"><span v-color='colorD'>第一个插槽尾部{{ vdata3 }}</span></template>
</SlotV>


<!-- 插槽组件 -->
<template>
    <div>
        <slot name="header" :vData="vData" mvalue="我是值1">我是插槽组件头部</slot>
        <slot name="body" :vData="vjsonData" mvalue="我是值2">我是后备内容</slot> <!-- 组件的slot默认值 -->
        <slot name="footer" :vData="vcolorD" mvalue="我是值3">我是插槽组件尾部</slot>
    </div>
</template>

<script>
export default {
  name: 'SlotV',
  data() {
    return {
      vData: "222222",
      vjsonData: {
        info: 2
      },
      vcolorD: 'red'
    }
  },
}
</script>

 4) 组件缓存(keep-alive)

  路由跳转后,缓存原来的页面。新页面返回后,回到跳转前的位置。

  •   includes(Array): 需要缓存的组件名称。
  •   excludes(Array): 不需要缓存的组件名称。
  •   max: 最多可以缓存的组件实例数量

页面缓存时触发的生命周期钩子函数

  • activated: 组件被看到时触发
  • deactivated: 组件失活时触发
<template>
  <div id="app">
    <div>
      <!-- route内置,设置路由对应组件所在位置 -->
      <keep-alive :includes="[menu1F, menu2F]">
        <router-view></router-view>
      </keep-alive>
    </div>
  </div>
</template>

<script>

export default {
  name: 'App',
  activated(){
    console.info("页面激活了");
  },
  deactivated(){
    console.info("页面失活了");
  },
}
</script>

8. 路由VueRouter

 路径和组件的对应关系。需要下载VueRouter模块才能使用。

官网地址:Vue Router      3.X版本

Vue Router | The official Router for Vue.js   

使用注意:vue2对应的VueRouter3.X   Vuex3.x;vue3对应的时VueRouter4.X Vuex4.x

1) 下载路由组件

#进入项目目录,安装模块
npm install vue-router@3.6.5

 2)安装注册route

import Vue from 'vue'
import VueRouter from 'vue-router' //引入模块

Vue.use(VueRouter) //安装注册

const router = new VueRouter() //创建路由对象
new Vue({
  render: h => h(App),
  router:router              //注入路由对象到vue实例, router:router可以简写为router
}).$mount('#app')

3) 创建需要的组件,并配置相应规则(建议组件放在views目录下)

在views目录下创建相应的组件文件,同时在route实例中定义路由规则

1. 定义路由规则

 routes参数介绍:

  • path: string, //路径
  • component: Component; //页面组件
  • name: string; // 命名路由-路由名称
  • components: ( ComponentName | ()=>import('页面地址') ); // 命名视图组件
  • redirect: string | Location | Function; // 路径重定向
  • props: boolean | string | Function; // 路由组件传递参数
  • alias: string | Array<string>; // 路由别名
  • children: Array<RouteConfig>; // 嵌套子路由,在嵌套页面需要设置子路由出口,路由地址不需要包含父级路由地址(http://localhost:8080/secondM2
  • beforeEnter?: (to: Route, from: Route, next: Function) => void; // 路由单独钩子
  • meta: any; // 自定义标签属性,比如:是否需要登录
  • icon: any; // 图标// 2.6.0+
  • caseSensitive: boolean; // 匹配规则是否大小写敏感?(默认值:false)
  • pathToRegexpOptions: Object; // 编译正则的选项
  • linkActiveClass: string , //模糊匹配类名
  • linkExactActiveClass: string  //精确匹配类名
  • mode: 'hash' //路由模式,默认hash(http://localhost:8080/#/m1),history模式(地址中不包含# http://localhost:8080/m1)需要后端做相关配置(routes路由模式设置为history时后端配置-CSDN博客
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

import Menu1 from "@/views/Menu1.vue";
import Menu2 from "@/views/Menu2.vue";
import Menu3 from "@/views/Menu3.vue";
import NotFound from "@/views/NotFound.vue";
import SecondMenu1 from "@/views/SecondMenu1.vue";
import SecondMenu2 from "@/views/SecondMenu2.vue";
const router = new VueRouter({
  routes: [
    {path: '/', redirect: '/m1'}, //重定向
    {name: 'n1', path:'/m1', component: Menu1 ,
     children:[
      {path:'/secondM1', component: SecondMenu1 },
      {path:'/secondM2', component: SecondMenu2 },
     ]
    },  //path -- 导航路径下, component-- 组件路径
    {path:'/m2/:words?', component: Menu2 },
    {name: 'n3', path:'/m3/:words', component: Menu3 },
    {path: '*', component: NotFound} //任意匹配
  ],
  linkActiveClass: 'active', //模糊匹配类名
  linkExactActiveClass: 'exact-active', //精确匹配类名
  mode: 'history' //路由模式,默认hash,history模式需要后端做相关配置
})
export default router;

2. 使用<a>标签设置导航

<a href="#/m1?key=menu111111">菜单一</a>

注意:href中要有#/  

3.使用声明式导航<router-link>

配置to参数,可以实现导航激活时高亮

.a.router-link-active: 模糊匹配,可以匹配多级菜单

.a.router-link-exact-active: 精确匹配,只能匹配一级菜单

<template>
  <div id="app">
    <div class="nav">
      <!-- 声明式导航,等价<a href,且可以实现激活时高亮-->
      <router-link to="/m1">菜单一</router-link>
      <router-link to="/m2">菜单二</router-link>
      <router-link to="/m3">菜单三</router-link>
    </div>
    <div>
      <!-- route内置,设置路由对应组件所在位置 -->
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
    }
  },
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.nav a.router-link-active { 
  background-color: red;
}
</style>

注意:组件名称由两个单词组成,否则容易报错

d2ada4a26df947caa2ea919a6f9b4d6b.png

 4. 跳转传参

1)查询参数传参,适合传递多个参数

设置参数:to='/路径名?参数名=参数值&参数名=参数值'

接受参数:$route.query.参数名 

2)动态路由传参,适合单个参数

配置动态路由的path: path:“/路径名/:参数名”(此时限制参数值必须传,不传参数值的时候会显示空白。参数名后加?可以去掉这个限制。)

跳转: to="/路径名/参数值"

接收参数: $route.params.参数名

routes: [
    {path:'/m1', component: Menu1 },  //导航路径下
    {path:'/m2/:words?', component: Menu2 },
    {path:'/m3/:words', component: Menu3 }  //path -- 导航路径下, component-- 组件路径
  ],

<div class="nav">
      <!-- 声明式导航,等价<a href,且可以实现激活时高亮-->
      <router-link to="/m1?key=menu111111">菜单一</router-link>
      <router-link to="/m2">菜单二</router-link>
      <router-link to="/m3/menu33333">菜单三</router-link>
    </div>

<template>
    <div>
        菜单一{{ $route.query.key }}
    </div>
</template>

<template>
    <div>
        菜单三{{ $route.params.words}}
    </div>
</template>

 5. 编程式导航-路由跳转及传参

<div>
  <input v-model="pathSearch">
  <button @click="routeChange">路由跳转</button>
</div>

 1)path路径跳转

methods: {
    routeChange(){
      // this.$router.push('/m2');
      this.$router.push({
        path: '/m1',
        query: {
          key: '路由跳转1'
        }
      })
    },
},

 2)name跳转(适合路径较长的情况)

methods: {
    routeChange(){
      // this.$router.push({
      //   name: 'n1',
      //   query: {
      //     key: this.pathSearch
      //   }
      // })
      this.$router.push({
        name: 'n3',
        params: {
          words: this.pathSearch
        }
      })
    },
},

异常:重复点击按钮时会报错Avoided redundant navigation to current location: "/". NavigationDuplicated: Avoided redundant navigation to current location: "/".

992655ac427d44f9b89e9c9e86f6d229.png

解决方案:错误 “Avoided redundant navigation to current location...” 的解决方案-CSDN博客

4) 配置导航栏及路由出口

 在vue实例挂载组件上配置路由导航,及组件出口

<template>
  <div id="app">
    <div class="nav">
      <!-- 声明式导航,等价<a href,且可以实现激活时高亮-->
      <router-link to="/m1?key=menu111111">菜单一</router-link>
      <router-link to="/m2">菜单二</router-link>
      <router-link to="/m3/menu33333">菜单三</router-link>
    </div>
    <div>
      <!-- route内置,设置路由对应组件所在位置 -->
      <router-view></router-view>
    </div>
  </div>
</template>

5)$router常用函数

  • $router.back():  返回上一页没有参数直接使用
  • $router.go(n): 前进或后退n步
  • $router.push(String|Object): 跳转

  • 64
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值