第三部分 Vue讲解(22-25)(代码版)

发布于:2024-04-28 ⋅ 阅读:(41) ⋅ 点赞:(0)

22.自定义指令

22.1 自定义指令基本语法

22.1.2 自定义指令.vue

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--自定义指令
自定义指令:自己定义的指令,可以封装一些dom操作,扩展额外功能
1.全局注册-语法(main.js中定义):
Vue.directive('指令名',{
  "inserted"(el){
    //可以对el标签,扩展额外功能
    el.focus()
  }
}
2.局部注册-语法:
directives:{
  "指令名":{
    inserted(){
      //可以对el标签,扩展额外功能
      el.focus()
    }
  }
}

自定义指令的使用:<input v-指令名 type="text">
-->

<!--自定义指令-指令的值
需求:实现一个color指令-传入不同的颜色,给标签设置文字颜色
语法:在绑定指令时,可以通过“等号”的形式为指令 绑定具体的参数值
<div v-color="color">内容</div>
通过binding.value可以拿到指令值,指令值修改会触发update函数
directives:{
  color:{
    inserted(el,binding){
      el.style.color=binding.value
    },
    update(el,binding){
      el.style.color=binding.value
    }
  }
}
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

22.1.2 App.vue

<template>
  <div>
    <h1 v-color="color1">自定义指令1</h1>
    <h1 v-color="color2">自定义指令2</h1>
    <input v-focus ref="inp" type="text">

  </div>
</template>

<script>
export default {
  //1.全局注册指令
  /*mounted(){
    this.$refs.inp.focus()
  }*/

//  2.局部注册指令
  directives:{
    //指令名:指令的配置项
    focus:{
      inserted(el){
        el.focus()
      }
    },
    color:{
      //1.inserted提供的是元素被添加到页面中时的逻辑
      inserted(el,binding){
        // console.log(el);
        //binding.value就是指令的值
        el.style.color=binding.value
      },
    //  2.update指令的值修改时触发,提供值变化后,dom更新的逻辑
      update(el,binding){
        console.log("指令的值修改了")
        el.style.color=binding.value
      }
    }
  },
  data(){
    return{
      color1:"red",
      color2:"orange"
    }
  }
}
</script>

<style>
</style>

22.2 自定义指令(v-loading指令封装)

22.2.1 自定义指令

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--自定义指令:v-loading指令封装
场景:实际开发过程中,发送请求需要时间,在请求的数据未回来时,页面会处于空白状态=>用户体验不好
需求:封装一个v-loading指令,实现加载中的效果
分析:(1)本质loading效果就是一个蒙层,盖在了盒子上;
     (2)数据请求中,开启loading状态,添加蒙层;
     (3)数据请求完毕,关闭loading状态,移除蒙层;
实现:(1)准备一个loading类,通过伪元素定位,设置宽高,实现蒙层;
     (2)开启关闭loading状态(添加移除蒙层),本质只需要添加移除类即可;
     (3)结合自定义指令的语法及逆行封装复用;
.loading:before{
  content:"";
  position:absolute;
  left:0;
  top:0;
  width:100%;
  height:100%;
  background:#fff url("./loading.gif") no-repeat center;
}
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

22.2.2 App.vue

<template>
  <div class="box" v-loading="isloading">
    <ul>
      <li v-for="item in list" :key="item.id" class="news">
        <div class="left">
          <div class="title">{{ item.title }}</div>
          <div class="info">
            <span>{{ item.source }}</span>
            <span>{{ item.time }}</span>
          </div>
        </div>
        <div class="right">
          <img :src="item.img" alt="">
        </div>
      </li>
    </ul>
  </div>
</template>
<!--
接口地址:http://hmajax.itheima.net/api/news
请求方式:get
-->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

<script>
// import axios from 'axios'
export default {
  data() {
    return {
      list: [],
      isloading: true
    }
  },
  async created() {
    //  1.发送请求获取数据
    const res = await axios.get("http://hmajax.itheima.net/api/news")
    setTimeout(() => {
      //  2.更新到 list 中,用于页面渲染v-for
      this.list = res.data.data
      this.isLoading = false
    }, 2000)
  },
  directives: {
    loading: {
      inserted(el, binding) {
        binding.value ? el.classList.add("loading") : el.classList.remove('loading')
      },
      update(el, binding) {
        binding.value ? el.classList.add("loading") : el.classList.remove('loading')
      }
    }
  }

}
</script>

<style>
.loading:before {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
  background: #fff url("./img/loading.gif") no-repeat;
}
</style>

23.插槽

23.1 默认插槽

23.1.1 默认插槽

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--插槽-默认插槽
作用:让组件内部的一些结构支持自定义,只能够完成一个定制位置
需求:要在页面中显示一个对话框,封装成一个组件;
问题:组件的内容部分,不希望写死,希望能使用的时候自定义
插槽基本语法:
1.组件内需要定制的结构部门,改用<slot></slot>占位
2.使用组件时,<MyDialog></MyDialog>标签内部,传入结构替换slot;
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

23.1.2 App.vue

<template>
  <div>
<!--    2.使用插槽:在使用标签内,填上插槽要添加的东西(可插入很多东西)-->
<!--     使用标签时,添加的内容将会填写到调用组件中的slot标签中-->
    <MyDialog>确定要删除吗?</MyDialog>
    <MyDialog>确定要退出系统吗?</MyDialog>
  </div>
</template>
<!--使用组件时
<MyDialog>你确定要退出本系统吗?</MyDialog>
此处的内容(你确定要退出本系统吗)就是要提交到<slot>插槽的位置
-->
<!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->

<script>
import MyDialog from "./components/MyDialog"

// import axios from 'axios'
export default {
  data() {
    return {}
  },
  components: {
    MyDialog
  }

}
</script>

<style>
.loading:before {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
}
</style>

23.1.3 MyDialog.vue

<template>
<div class="dialog">
<!--  头部-->
  <div class="dialog-header">
    <h3>友情提示</h3>
    <span class="close">X</span>
  </div>

<!--  主体-->
  <div class="dialog-content">
    <!--      中间(此处)的内容需要定制-->
<!--   1.在需要定制的位置,使用slot占位 -->
    <slot></slot>

  </div>

<!--  尾部-->
  <div class="dialog-footer">
    <button>取消</button>
    <button>确认</button>
  </div>
</div>
</template>

<script>
export default {
  name: "MyDialog"
}
</script>

<style scoped>

</style>

23.2 后备内容(插槽默认的内容)

23.2.1 后备内容

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--
通过插槽完成了内容的定制,传什么显示什么,如果不传,则是空白
插槽后备内容:封装组件时,可以为预留的`<slot>`插槽提供后备内容(默认内容)
语法:在<slot>标签内,放置内容,作为默认显示内容
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

23.2.2 App.vue

<template>
  <div>
<!--    2.使用插槽:在使用标签内,填上插槽要添加的东西(可插入很多东西)-->
<!--     使用标签时,添加的内容将会填写到调用组件中的slot标签中-->
    <MyDialog>确定要删除吗?</MyDialog>
    <MyDialog>确定要退出系统吗?</MyDialog>
    <MyDialog></MyDialog>   <!--此处未传入值,则会显示插槽默认的内容-->
  </div>
</template>
<!--使用组件时
<MyDialog>你确定要退出本系统吗?</MyDialog>
此处的内容(你确定要退出本系统吗)就是要提交到<slot>插槽的位置
-->
<!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->

<script>
import MyDialog from "./components/MyDialog"

// import axios from 'axios'
export default {
  data() {
    return {}
  },
  components: {
    MyDialog
  }

}
</script>

<style>
.loading:before {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
}
</style>

23.2.3 MyDialog.vue

<template>
<div class="dialog">
<!--  头部-->
  <div class="dialog-header">
    <h3>友情提示</h3>
    <span class="close">X</span>
  </div>

<!--  主体-->
  <div class="dialog-content">
    <!--      中间(此处)的内容需要定制-->
<!--   1.在需要定制的位置,使用slot占位,在slot占位符中添加的内容就是默认显示内容(当在调用该插槽时,无内容,则将显示该后备内容,否则,显示添加的内容) -->
    <slot>后备内容</slot>

  </div>

<!--  尾部-->
  <div class="dialog-footer">
    <button>取消</button>
    <button>确认</button>
  </div>
</div>
</template>

<script>
export default {
  name: "MyDialog"
}
</script>

<style scoped>

</style>

23.3 具名插槽

23.3.1 具名插槽

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--具名插槽(就是有具体名字的插槽)
需求:一个组件内有多处结构,需要外部传入标签,进行定制
具名插槽语法:
 1.多个slot使用name属性区分名字,name对应的数据就相当于每个插槽的具体唯一名字
 例如:<div class="dialog-header">
        <slot name="head"></slot>
      </div>
      <div class="dialog-content">
        <slot name="content"></slot>
      </div>
      <div class="dialog-footer">
        <slot name="footer"></slot>
      </div>

 2.template配合v-slot:名字来分发对应标签
 例如:<MyDialog>
        <template v-slot:head>
          大标题
        </template>
        <template v-slot:content>
           内容文本
        </template>
        <template v-slot:footer>
          <button>按钮</button>
        </template>
      </MyDialog>

3.v-slot:插槽名  可以简化为 #插槽名
     <MyDialog>
        <template #head>
          大标题
        </template>
        <template #content>
           内容文本
        </template>
        <template #footer>
          <button>按钮</button>
        </template>
      </MyDialog>
-->
<!--
注意:一旦插槽有了名字,就是具名插槽,只支持定向分发
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

23.3.2 App.vue

<template>
  <div>
    <!--    2.使用插槽:在使用标签内,填上插槽要添加的东西(可插入很多东西)-->
    <!--     使用标签时,添加的内容将会填写到调用组件中的slot标签中-->
    <!--    <MyDialog>确定要删除吗?</MyDialog>
        <MyDialog>确定要退出系统吗?</MyDialog>
        <MyDialog></MyDialog>-->   <!--此处未传入值,则会显示插槽默认的内容-->
    <MyDialog>
      <!--      需要通过template包裹分发的结构,包成一个整体-->
      <template #head>
        <div>大标题</div>
      </template>

      <template #content>
        <div>内容文本</div>
      </template>

      <template #footer>
        <template>
          <button>确认</button>
          <button>取消</button>
        </template>
      </template>
    </MyDialog>
  </div>
</template>
<!--使用组件时
<MyDialog>你确定要退出本系统吗?</MyDialog>
此处的内容(你确定要退出本系统吗)就是要提交到<slot>插槽的位置
-->
<!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->

<script>
import MyDialog from "./components/MyDialog"

// import axios from 'axios'
export default {
  data() {
    return {}
  },
  components: {
    MyDialog
  }

}
</script>

<style>
.loading:before {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
}
</style>

23.3.3 MyDialog.vue

<template>
  <div class="dialog">
    <!--  头部-->
    <div class="dialog-header">
      <slot></slot>
    </div>

    <!--  主体-->
    <div class="dialog-content">
        <slot name="content"></slot>
    </div>

    <!--  尾部-->
    <div class="dialog-footer">
      <slot name="footer"></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: "MyDialog"
}
</script>

<style scoped>

</style>

23.4 作用域插槽

23.4.1 作用域插槽

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--作用域插槽:是插槽的一个传参语法-->
<!--作用域插槽:定义slot插槽的同时,是可以传值的,给插槽上可以绑定数据,将来使用组件时可以使用-->
<!--场景:封装表格组件
1.父传子,动态渲染表格内容;
2.利用默认插槽,定制操作列;
3.删除或查看都要用到当前项的id,属于组件内部的数据;
通过作用域插槽传值绑定,进而使用
-->
<!--作用域插槽基本使用步骤:
1.给slot标签,以添加属性的方式传值
  <slot :id="item.id" msg="测试文本"></slot>
2.所有添加的属性,都会被收集到一个对象中
  {id:3,msg:"测试文本"}
3.在template中,通过'#插槽名=“obj”'接收调用此插槽时发送的数据,默认插槽名为default
<MyTable :list='list'>
  <template #default="obj">
    <button @click="del(obj.id)">删除</button>
  </template>
</MyTable>
  -->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

23.4.2 App.vue

<template>
  <div>
    <MyTable :data="list">
<!--      3.通过template #插槽名=“变量名”,接收-->
<!--      obj:就是接收来自MyTable组件的对象数据-->
      <template #default="obj">
        {{obj}}
        <button @click="del(obj.row.id)">删除</button>
      </template>
    </MyTable>

    <MyTabe :data="list2">
      <template #default="{row}">

        <button @click="show(row)">查看</button>
      </template>
    </MyTabe>
  </div>
</template>
<!--使用组件时
<MyDialog>你确定要退出本系统吗?</MyDialog>
此处的内容(你确定要退出本系统吗)就是要提交到<slot>插槽的位置
-->
<!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->

<script>
import MyTable from "./components/MyTable"
export default {
  data() {
    return {
      list: [
        {id: 1, name: "yuer", age : 18},
        {id: 2, name: "yuer2", age : 19},
        {id: 3, name:"yuer3", bag :17},
      ],
      list2: [
        {id: 1, name: "yuer", age : 18},
        {id: 2, name: "yuer2", age : 19},
        {id: 3, name:"yuer3", bag :17},
      ]
    }
  },
  methods:{
    del(id){
      this.list=this.list.filter(item=>item)
    },
    show(row){
      console.log(row);
    }
  },
  components: {
    MyTable
  }

}
</script>

<style>
.loading:before {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
}
</style>

23.4.3 MyTable.vue

<template>
  <div>
    <tr v-for="(item,index) in data" :key="item.id">
      <td>{{ index + 1 }}</td>
      <td>{{ item.name }}</td>
      <td>{{ item.age }}</td>
      <td>
<!--        1.给slot标签,添加属性的方式传值-->
        <slot :row="item" msg="测试数据"></slot>

<!--        2.将所有的属性,添加到一个对象中-->
<!--        {
              row:{id:2,name:'yuer',age:18},
              msg:{"测试文本"}
}-->
      </td>
    </tr>
  </div>
</template>

<script>
export default {
  name: "MyDialog"
}
</script>

<style scoped>
</style>

24.路由

24.1 单页应用程序&路由简单介绍

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--单页应用程序-->
<!--单页应用程序:SPA-Single Page Application:指的是 所有功能 在一个html页面上实现-->
<!--例如:网易云音乐https://music.163.com/(单页面应用:整个导航没变化)-->
<!--例如:京东、淘宝等(多页面应用:导航栏发生变化)-->
<!--单页面应用 VS 多页面应用-->
<!--
开发分类   实现方式       页面性能        开发效率   用户体验   学习成本   首屏加载  SEO(搜索引擎优化)
单页      一个html页面   按需更新性能高      高      非常好      高       慢      差
多页      多个html页面   整页面更新性能低    中等     一般       中等      快      优
-->
<!--单页面、多页面应用的适用:
单页面(vue):系统类网站/内部网站/文档类网站/移动端站点
多页面:公司官网/电商类网站
-->
<!--单页面应用程序,之所以开发效率高,性能高,用户体验的的原因是:页面是按需更新的
要按需更新,首先就需要明确:访问路径和组件的对应关系
访问路径和组件的对应关系如何确定呢?路由
-->

<!--路由:
生活中的路由:设备和ip的映射关系(路由器)
Vue中的路由:路径和组件的映射关系
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

24.2 VueRouter的介绍

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--VueRouter的介绍
目标:1.认识vue提供的路由插件:VueRouter;
     2.掌握VueRouter的基本使用步骤;
作用:修改地址栏路径时,切换显示匹配的组件;
说明:Vue官方的一个路由插件,是一个第三方包;
官网:https://v3.router.vuejs.org/zh/
-->
<!--VueRouter的使用步骤(5+2)
1.前5步基础步骤:初始化步骤(固定)
(1)下载:idea打开项目终端下载VueRouter模块到当前工程,版本3.6.5(vue2);
 yarn add vue-router@3.6.5 或 pnpm install vue-router@3.6.5(注:查看vue路由版本的指令:pnpm list vue-router)
(2)引入;
 import VueRouter from 'vue-router'

(3)安装注册(插件的初始化);
 Vue.use(VueRouter)
 (注:vue相关插件的使用都需要进行安装注册)
(4)创建路由对象;
 const router=new VueRouter()
 (注:此时创建的vue实例和任何事件都没有关系)

(5)注入,将路由对象注入到new Vue实例中,建立关联;
 new Vue({
  render:h=>h(App),
  router
 }).$mount('#app')

 注意:当完成前5步基础步骤时,地址栏中就会自动加一个#/,说明此时,被路由所管理

2.后2步核心步骤
(1)创建需要的组件(views目录---视图),配置路由规则(路径组件的匹配关系);
   1)新的.vue文件(需要放在views目录(视图)中)
       Find.vue/My.vue/Friend.vue
       在main.js中导入该vue文件
(2)配置导航,配置路由出口router-view(路径匹配的组件显示的位置);

-->
<!--  Vue2 和 Vue3 对应的路由插件使用
2(Vue2) 3(VueRouter3.x) 3(Vuex3.x)
3(Vue3) 4(VueRouter4.x) 4(Vuex4.x)
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

24.3 组件存放目录问题

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--
路由相关的组件,为什么要放在views目录中呢?
组件分类:.vue文件分为2类(页面组件 & 复用组件),(注意:.vue文件本质无区别)
(1)页面组件:放在views目录中
(2)复用组件:放在components目录中
组件分类后,更易维护
(1)src/views文件夹
     页面组件:页面展示,配合路由使用
(2)src/components文件夹
     复用组件:展示数据,常用于封装复用
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>
</style>

24.4 VueRouter的完整实现步骤

24.4.1 main.js

import Vue from 'vue'
import App from './App.vue'

//路由的使用步骤(5+2)
//5个基础步骤:

//1.下载(版本):项目终端中下载
//2.引入;
import VueRouter from "vue-router";

import Find from "./views/Find.vue"
import My from "./views/My.vue"
import Friend from "./views/Friend.vue"

//3.安装注册 (Vue.use(vue相关的插件))
Vue.use(VueRouter)   //将VueRouter 放到use()内,实则会实现VueRouter发生初始化变化
//4.创建路由对象(router可以是其他名字,但要new Vue中与其对应)
// const router=new VueRouter()
const r = new VueRouter({
        //核心步骤1:创建需要的组件(views目录),配置路由规则们(多个路由规则)
        //routes:路由规则们
        //route:一条路由规则{path:路径,component:组件}
        routes: [
            {path: "/find", component: Find},  //每条规则(地址栏路径(path)和组件(component)的对应)
            {path: "/my", component: My},
            {path: "/friend", component: Friend},
        ]
    }
)
//5.注入new Vue中,建立关联


Vue.config.productionTip = false
//5.将插件对象注入到new Vue实例中
new Vue({
    render: h => h(App),
    // router   //当路由对象名和router相同时,可简写成router
    router: r   //当路由对象名和router不同时,需要对应路由对象名
}).$mount('#app')

24.4.2 App.vue

<template>
  <div>
    <div class="footer_wrap">
      <a href="#/find">发现音乐</a>
      <a href="#/my">我的音乐</a>
      <a href="#/friend">朋友</a>
    </div>

    <div class="top">
      <!--      路由出口: 该标签是用来控制组件所展示的位置-->
      <!--      该标签也是vue内部的标签,当该标签的位置决定着组件的位置(该标签放在哪里,组件就在哪里显示)/-->
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {}
</script>

<style>
.footer_wrap {
  position: fixed;
  left: 0;
  top: 0;
  display: flex;
  width: 100%;
  height: 100%;
}
</style>

24.4.3 Find.vue

<template>
  <div>
    <p>发现音乐</p>
    <p>发现音乐</p>
    <p>发现音乐</p>
  </div>
</template>

<script>
export default {
  name: "FindMusic"   //此处是因为eslint的命名规范,组件名必须要至少两个单词命名,故此处的name的值是由多个单词组成
}
</script>

<style scoped>

</style>

24.4.4 My.vue

<template>
<div>
  <p>我的歌单</p>
  <p>我的歌单</p>
  <p>我的歌单</p>
</div>
</template>

<script>
export default {
  name: "MyMusic"  //此处是因为eslint的命名规范,组件名必须要至少两个单词命名,故此处的name的值是由多个单词组成
}
</script>

<style scoped>

</style>

24.4.5 Friend.vue

<template>
<div>
  <p>朋友歌单</p>
  <p>朋友歌单</p>
  <p>朋友歌单</p>
</div>
</template>

<script>
export default {
  name: "FriendMusic"  //此处是因为eslint的命名规范,组件名必须要至少两个单词命名,故此处的name的值是由多个单词组成
}
</script>

<style scoped>

</style>

总结:
路由的使用步骤(5+2)
5步基础步骤:
(1)项目终端中下载
(2)(3)(4)(5)在main.js文件中实现
2步核心步骤:
(1)创建子组件vue文件,在main.js文件中导入,并将这些文件和路径地址进行匹配;
(2)在根组件中使用这些子组件,App.js文件

25.路由进阶

25.1 路由的封装抽离

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--路由的封装抽离
问题:所有的路由配置都堆在main.js中合适吗?
目标:将路由模块抽离出来;
好处:拆分模块,利于维护;
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

25.1.1 router目录—index.js(路由的封装)

//存放路由规则,在使用路由规则时,只需导入该规则即可
// 核心步骤:(1)创建router目录下的index.js文件;(2)将配置的路由相关内容存放在该文件中,之后在main.js中直接导入该index.js文件即可
//路由的使用步骤(5+2)
//5个基础步骤:

//路由的使用步骤(5+2)
//5个基础步骤:

//1.下载(版本):项目终端中下载
//2.引入;
import Vue from 'vue'
import VueRouter from "vue-router";
//找文件时,推荐使用绝对路径,使用@标识符代表标识路径
//@代表src目录

// import Find from "../views/Find.vue"
// import My from "../views/My.vue"
// import Friend from "../views/Friend.vue"
import Find from "@/views/Find"
import My from "@/views/My"
import Friend from "@/views/Friend"

//3.安装注册 (Vue.use(vue相关的插件))
// eslint-disable-next-line no-undef
Vue.use(VueRouter)   //将VueRouter 放到use()内,实则会实现VueRouter发生初始化变化
//4.创建路由对象(router可以是其他名字,但要new Vue中与其对应)
// const router=new VueRouter()
const router = new VueRouter({
        //核心步骤1:创建需要的组件(views目录),配置路由规则们(多个路由规则)
        //routes:路由规则们
        //route:一条路由规则{path:路径,component:组件}
        routes: [
            {path: "/find", component: Find},  //每条规则(地址栏路径(path)和组件(component)的对应)
            {path: "/my", component: My},
            {path: "/friend", component: Friend},
        ]
    }
)

//导出router
export default router

25.1.2 main.js 导入封装路由

import Vue from 'vue'
import App from './App.vue'

//导入indext.js中的router
import router from './router/index'

Vue.config.productionTip = false
//5.将插件对象注入到new Vue实例中
new Vue({
    render: h => h(App),
    router   //当路由对象名和router相同时,可简写成router
    // router: r   //当路由对象名和router不同时,需要对应路由对象名
}).$mount('#app')

25.1.3 App.vue

<template>
  <div>
    <div class="footer_wrap">
      <a href="#/find">发现音乐</a>
      <a href="#/my">我的音乐</a>
      <a href="#/friend">朋友</a>
    </div>

    <div class="top">
      <!--      路由出口: 该标签是用来控制组件所展示的位置-->
      <!--      该标签也是vue内部的标签,当该标签的位置决定着组件的位置(该标签放在哪里,组件就在哪里显示)/-->
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {}
</script>

<style>
.footer_wrap {
  position: fixed;
  left: 0;
  top: 0;
  display: flex;
  width: 100%;
  height: 100%;
}
</style>

25.1.4 Find.vue

<template>
  <div>
    <p>发现音乐</p>
    <p>发现音乐</p>
    <p>发现音乐</p>
  </div>
</template>

<script>
export default {
  name: "FindMusic"   //此处是因为eslint的命名规范,组件名必须要至少两个单词命名,故此处的name的值是由多个单词组成
}
</script>

<style scoped>

</style>

25.1.5 Friend.vue

<template>
<div>
  <p>朋友歌单</p>
  <p>朋友歌单</p>
  <p>朋友歌单</p>
</div>
</template>

<script>
export default {
  name: "FriendMusic"  //此处是因为eslint的命名规范,组件名必须要至少两个单词命名,故此处的name的值是由多个单词组成
}
</script>

<style scoped>

</style>

25.1.6 My.vue

<template>
<div>
  <p>我的歌单</p>
  <p>我的歌单</p>
  <p>我的歌单</p>
</div>
</template>

<script>
export default {
  name: "MyMusic"  //此处是因为eslint的命名规范,组件名必须要至少两个单词命名,故此处的name的值是由多个单词组成
}
</script>

<style scoped>

</style>

25.2 使用router-link替代a标签实现高亮

25.2.1 使用router-link替代高亮

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--router-link 声明式导航-导航链接
需求:实现导航高亮效果
vue-router提供了一个全局组件router-link(取代a标签)
(1)能跳转,配置to属性指定路径(必须),本质还是a标签,to无需#
(2)能高亮,默认就会提供高亮类名,可以直接设置高亮样式,自带激活时的类名
-->

<!--router-link 声明式导航--默认提供两个类名
说明:我们发现router-link 自动给当前导航添加了两个高亮类名
(1)router-link-exact-active: 精确匹配
     to="/my"  只可以匹配  /my
(2)router-link-active: 模糊匹配(用的多)
     to="/my"  可以匹配 /my  /my/a  /my/b  ....,,
-->

<!--router-link 声明式导航--默认提供两个类名
说明:router-link的两个高亮类名太长了,我们希望能定制?
在index.js文件中重命名
const router=new VueRouter({
  router:[...],
  linkActiveClass:"类名1",  //类名1和类名2 是自定义的类名,激活时使用的是自定义类名
  linkExactActiveClass:"类名2"
})
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

25.2.2 index.js

//存放路由规则,在使用路由规则时,只需导入该规则即可
// 核心步骤:(1)创建router目录下的index.js文件;(2)将配置的路由相关内容存放在该文件中,之后在main.js中直接导入该index.js文件即可
//路由的使用步骤(5+2)
//5个基础步骤:

//路由的使用步骤(5+2)
//5个基础步骤:

//1.下载(版本):项目终端中下载
//2.引入;
import Vue from 'vue'
import VueRouter from "vue-router";
//找文件时,推荐使用绝对路径,使用@标识符代表标识路径
//@代表src目录

// import Find from "../views/Find.vue"
// import My from "../views/My.vue"
// import Friend from "../views/Friend.vue"
import Find from "@/views/Find"
import My from "@/views/My"
import Friend from "@/views/Friend"

//3.安装注册 (Vue.use(vue相关的插件))
// eslint-disable-next-line no-undef
Vue.use(VueRouter)   //将VueRouter 放到use()内,实则会实现VueRouter发生初始化变化
//4.创建路由对象(router可以是其他名字,但要new Vue中与其对应)
// const router=new VueRouter()
const router = new VueRouter({
        //核心步骤1:创建需要的组件(views目录),配置路由规则们(多个路由规则)
        //routes:路由规则们
        //route:一条路由规则{path:路径,component:组件}
        routes: [
            {path: "/find", component: Find},  //每条规则(地址栏路径(path)和组件(component)的对应)
            {path: "/my", component: My},
            {path: "/friend", component: Friend},
        ],
    //link自定义高亮类名
    linkActiveClass: 'active',  //模糊匹配类名
    linkExactActiveClass:'exact-active'   //精确匹配类名
    }
)

//导出router
export default router

25.2.3 main.js

import Vue from 'vue'
import App from './App.vue'

//导入indext.js中的router
import router from './router/index'

Vue.config.productionTip = false
//5.将插件对象注入到new Vue实例中
new Vue({
    render: h => h(App),
    router   //当路由对象名和router相同时,可简写成router
    // router: r   //当路由对象名和router不同时,需要对应路由对象名
}).$mount('#app')

25.2.4 App.vue

<template>
  <div>
    <div class="footer_wrap">
      <router-link to="/find">发现音乐歌单</router-link>
      <router-link to="/my">我的歌单</router-link>
      <router-link to="/friend">朋友的歌单</router-link>
    </div>

    <div class="top">
<!--      路由出口: 该标签是用来控制组件所展示的位置-->
<!--      该标签也是vue内部的标签,当该标签的位置决定着组件的位置(该标签放在哪里,组件就在哪里显示)/-->
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {}
</script>

<style>
body{
  margin:0;
  padding:0;
}
.footer_wrap {
  position: relative;
  left: 0;
  top: 0;
  display: flex;
  width: 100%;
  text-align:center;
  background-color: #333;
  color: #ccc;
}
.footer_wrap a{
  flex:1;
  text-decoration: none;
  padding:20px 0;
  line-height: 20px;
  background-color: #333;
  color:#ccc;
  border:1px solid black;
}
/*router-link-active:模糊匹配(常使用)
to="/find"  => 地址栏匹配  /find  /find/one  /find/two
*/
/*.footer_wrap a.router-link-active{
  background-color: purple;
}*/
/*对router-link默认自带的router-link-active类进行重命名*/
.footer_wrap a.active{
  background-color: purple;
}
/*
router-link-exact-active:精确匹配(不常使用)
to="/find"  => 地址栏匹配 /find
*/


/*.footer_wrap a.router-link-exact-active{
  background-color: purple;
}*/
/*对router-link默认自带的类router-link-exact-active进行重命名*/
/*.footer_wrap a.exact-active{
  background-color: purple;
}*/

.footer_wrap a:hover{
  background-color: #555;
}
</style>

子组件与上节相同

25.3 声明式导航-跳转传参

25.3.1 声明式导航-跳转传参

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--
目标:在跳转路由时,进行传值
(1)查询参数传参;
(2)动态路由传参;
-->
<!--(1)查询参数传参
1)语法格式如下:
  to="/path?参数名1=值&参数名2=值"
2)对应页面组件接收传递过来的值
  $route.query.参数名
-->
<!--(2)动态路由传参
(1)配置动态路由(index.js文件中)
const router=new VueRouter({
  routers:[
  ...,
  {
    path:"/search/:words",
    component: Search
  }
  ]
})

(2)配置导航链接
  to="/path/参数值"

(3)对应页面组件接收传递过来的值
  $route.params.参数名
-->


<!--查询参数传参 和 动态路由传参之间的异同点
区别:
1.查询参数传参(比较适合传多个参数)
(1)跳转:to="/path?参数名=值&参数名2=值"
(2)获取:$route.query.参数名

2.动态路由传参(优雅简洁,传单个参数比较方便)
(1)配置动态路由:path:"/paht/参数名"
(2)跳转:to="/path/参数名"
(3)获取:$route.params.参数名

-->


<!--动态路由参数可选符
问题:配了路由path:"/search/:words" 为什么按下面步骤操作,会未匹配到组件,显示空白?
原因:/search/:words 表示,必须要传参数,如果不传参数,也希望匹配,可以加个可选符“?”
const router=new VueRouter({
  routes=[
    {path:"/",redirect:'/home'}
    {path:"/home",component:Home]},
    {path:"/search/:words?",component:Search}

})

-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

25.3.2 router—index.js

import Vue from 'vue'
import VueRouter from "vue-router";

import Home from "@/views/Home"
import Search from "@/views/Search"

Vue.use(VueRouter)   //将VueRouter 放到use()内,实则会实现VueRouter发生初始化变化
const router = new VueRouter({
        routes: [
            {path:"/home",component:Home},
            {path:"/search/:words",component:Search}
        ],
    }
)

//导出router
export default router

25.3.3 main.js

import Vue from 'vue'
import App from './App.vue'

import router from './router/index'

Vue.config.productionTip = false
//5.将插件对象注入到new Vue实例中
new Vue({
    render: h => h(App),
    router   //当路由对象名和router相同时,可简写成router
    // router: r   //当路由对象名和router不同时,需要对应路由对象名
}).$mount('#app')

25.3.4 App.vue

<template>
  <div id="app">
    <div class="link">
      <router-link to="/find">首页</router-link>
      <router-link to="/my">搜索页</router-link>
    </div>
    <!--      路由出口: 该标签是用来控制组件所展示的位置-->
    <router-view></router-view>
  </div>
</template>

<script>
export default {}
</script>

<style>
.link{
  height:50px;
  line-height:50px;
  background-color: #495150;
  display:flex;
  margin:-8px -8px 0 -8px;
  margin-bottom: 50px;
}

.footer_wrap {
  position: relative;
  left: 0;
  top: 0;
  display: flex;
  width: 100%;
  text-align: center;
  background-color: #333;
  color: #ccc;
}

.footer_wrap a {
  flex: 1;
  text-decoration: none;
  padding: 20px 0;
  line-height: 20px;
  background-color: #333;
  color: #ccc;
  border: 1px solid black;
}

/*router-link-active:模糊匹配(常使用)
to="/find"  => 地址栏匹配  /find  /find/one  /find/two
*/
/*.footer_wrap a.router-link-active{
  background-color: purple;
}*/
/*对router-link默认自带的router-link-active类进行重命名*/
.footer_wrap a.active {
  background-color: purple;
}

/*
router-link-exact-active:精确匹配(不常使用)
to="/find"  => 地址栏匹配 /find
*/


/*.footer_wrap a.router-link-exact-active{
  background-color: purple;
}*/
/*对router-link默认自带的类router-link-exact-active进行重命名*/
/*.footer_wrap a.exact-active{
  background-color: purple;
}*/

.footer_wrap a:hover {
  background-color: #555;
}
</style>

25.3.5 Home.vue

<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input type="text">
      <button>搜索一下</button>
    </div>

    <div class="hot-link">
      热门搜索:
<!--      查询参数传参-->
<!--      <router-link to="/search?key=发现歌单">发现歌单</router-link>-->
<!--      <router-link to="/search?key=我的歌单">我的歌单</router-link>-->
<!--      <router-link to="/search?key=朋友歌单">朋友歌单</router-link>-->
<!--      动态路由传参-->
      <router-link to="/search/发现歌单">发现歌单</router-link>
      <router-link to="/search/我的歌单">我的歌单</router-link>
      <router-link to="/search/朋友歌单">朋友歌单</router-link>

    </div>
  </div>
</template>

<script>
export default {
  name: "HomeComponent"
}
</script>

<style scoped>
.logo-box{

}
</style>

25.3.6 Search.vue

<template>
  <div class="search">
    <!--  查询参数传参-->
    <!--  <p>搜索关键字:{{$route.query.key}}</p>-->
    <!--  动态路由传参-->
    <p>搜索关键字:{{ $route.params.words }}</p>
    <p>搜索结果:</p>
    <ul>
      <li>..............</li>
      <li>..............</li>
      <li>..............</li>
      <li>..............</li>
      <li>..............</li>
      <li>..............</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "SearchComponent",
  created() {
    //  在created中,获取路由参数,this.$route.query.参数名 获取查询参数
    //  查询参数传参
    //   console.log(this.$route.query.key);

    //  在created中,获取路由参数,this.$route.params.参数名 获取动态路由参数
    //  动态路由传参
    console.log(this.$route.params.words)
  }
}
</script>

<style scoped>
.search {
  width: 400px;
  height: 240px;
  padding: 0 20px;
}
</style>

25.4 Vue路由-重定向

25.4.1 Vue路由-重定向

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--Vue路由-重定向
问题:网页打开,url默认是/路径,未匹配到组件时,会出现空白
说明:重定向->匹配path后,强制跳转path路径
语法:{path:匹配路径,redirect:重定向到的路径}
const router=new VueRouter({
  routes:[
  {path:"/",redirect:'/home'},
  {path:"/home",component:Home},
  {path:"/search/:words",component:Search}
  ]
})
-->
<!--vue路由-404
作用:当路径找不到匹配时,给个提示页面
位置:配置在整个路由最后
语法:path:"*"(任意路径)-前面不匹配就命中最后这个
const router=new VueRouter({
  routes:[
  {path:"/",redirect:'/home'},
  {path:"/home",component:Home},
  {path:"/search/:words",component:Search},
  {path:"*",component:NotFind}
  ]
})
-->

<!--vue路径-模式设置
问题:路由的路径看起来不自然,有#,能否切成真正路径形式?
(1)hash路由(默认),例如:http://localhost:8080/#/home
(2)history路由(常用),例如:http://localhost:8080/home(以后上线需要服务器端支持)
const router=new VueRouter({
  routes,
  mode:"history"
})
-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

25.4.2 router—index.js

import Vue from 'vue'
import VueRouter from "vue-router";

import Home from "@/views/Home"
import Search from "@/views/Search"
import NotFound from "@/views/NotFound"

Vue.use(VueRouter)   //将VueRouter 放到use()内,实则会实现VueRouter发生初始化变化
const router = new VueRouter({
        //注意:一旦采用了history模式,地址栏中就没有#,需要后台配置访问规则
        // mode: "hash",  //vue路径,设置模式(默认)
        mode: "history",  //vue路径,设置模式(常用)
        routes: [
            {path: "/", redirect: '/home'},
            {path: "/home", component: Home},
            {path: "/search/:words", component: Search},
            {path: "*", component: NotFound}  //vue路由-404
        ],
    }
)

//导出router
export default router

25.4.3 App.vue

<template>
  <div id="app">
    <div class="link">
      <router-link to="/find">首页</router-link>
      <router-link to="/my">搜索页</router-link>
    </div>
    <!--      路由出口: 该标签是用来控制组件所展示的位置-->
    <router-view></router-view>
  </div>
</template>

<script>
export default {}
</script>

<style>
.link{
  height:50px;
  line-height:50px;
  background-color: #495150;
  display:flex;
  margin:-8px -8px 0 -8px;
  margin-bottom: 50px;
}

.footer_wrap {
  position: relative;
  left: 0;
  top: 0;
  display: flex;
  width: 100%;
  text-align: center;
  background-color: #333;
  color: #ccc;
}

.footer_wrap a {
  flex: 1;
  text-decoration: none;
  padding: 20px 0;
  line-height: 20px;
  background-color: #333;
  color: #ccc;
  border: 1px solid black;
}

/*router-link-active:模糊匹配(常使用)
to="/find"  => 地址栏匹配  /find  /find/one  /find/two
*/
/*.footer_wrap a.router-link-active{
  background-color: purple;
}*/
/*对router-link默认自带的router-link-active类进行重命名*/
.footer_wrap a.active {
  background-color: purple;
}

/*
router-link-exact-active:精确匹配(不常使用)
to="/find"  => 地址栏匹配 /find
*/


/*.footer_wrap a.router-link-exact-active{
  background-color: purple;
}*/
/*对router-link默认自带的类router-link-exact-active进行重命名*/
/*.footer_wrap a.exact-active{
  background-color: purple;
}*/

.footer_wrap a:hover {
  background-color: #555;
}
</style>

25.4.4 NotFound.vue

<template>
<div>
  404
</div>
</template>

<script>
export default {
  name: "NotFound"
}
</script>

<style scoped>

</style>

其他文件见25.3

25.5 编程式导航

25.5.1 基本跳转

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--
问题一:点击按钮跳转如何实现?
编程式导航:用JS代码来进行跳转
两种语法:(1)path路径跳转(简易方便)
        (2)name命名路由跳转
-->
<!--(1)path路径跳转
this.$router.push('路由路径')(简写方式)
this.$router.push({  (完整写法)
  path:'路由路径'
})
-->
<!--(2)name命名路由跳转(适合path路径长的场景)
this.$router.push({
  name:'路由名'
})
{name:'路由名',path:'/path/xxx',component:xxx}
-->

<!--
问题二:点击搜索按钮,跳转需要传参如何实现?

-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

25.5.2 路由传参

<template>
  <div id="app">
    <!--    v-model相当于:value="XXX" @input="msg=XXX"-->
    <input v-model="msg" type="text">
    <input :value="msg" @input="msg=$event.target.value" type="text">
  </div>
</template>
<!--
问题二:点击搜索按钮,跳转需要传参如何实现?
两种传参方式:查询参数+动态路由传参
两种跳转方式,对于两种传参方式都支持:
(1)path路径跳转传参
a)query传参
this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
this.$router.push({
  path:'/路径',
  query:{
    参数名1:'参数值1',
    参数名2:'参数值2'
  }
})
b)动态路由传参,需要配置路由
this.$router.push('/路径/参数值')
this.$router.push({
  path:'/路径/参数值'
})
(2)name命名路由跳转传参
a)查询参数
this.$router.push({
  name:'路由名字',
  query:{参数名:参数值},
  params:{
    参数名:‘参数值’
  }
})
b)动态路由传参

-->
<script>
export default {}
</script>

<!--样式:-->
<style scoped>

</style>

25.5.3 index.js

import Vue from 'vue'
import VueRouter from "vue-router";

import Home from "@/views/Home"
import Search from "@/views/Search"
import NotFound from "@/views/NotFound"

Vue.use(VueRouter)   //将VueRouter 放到use()内,实则会实现VueRouter发生初始化变化
const router = new VueRouter({
        //注意:一旦采用了history模式,地址栏中就没有#,需要后台配置访问规则
        // mode: "hash",  //vue路径,设置模式(默认)
        mode: "history",  //vue路径,设置模式(常用)
        routes: [
            {path: "/", redirect: '/home'},
            {path: "/home", component: Home},
            {name:"search", path: "/search/:words?", component: Search},
            {path: "*", component: NotFound}  //vue路由-404
        ],
    }
)

//导出router
export default router

25.5.4 main.js

import Vue from 'vue'
import App from './App.vue'

import router from './router/index'

Vue.config.productionTip = false
//5.将插件对象注入到new Vue实例中
new Vue({
    render: h => h(App),
    router   //当路由对象名和router相同时,可简写成router
    // router: r   //当路由对象名和router不同时,需要对应路由对象名
}).$mount('#app')

25.5.5 Home.vue

<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input v-model="inpValue" type="text">
      <button @click="goSearch">搜索一下</button>
    </div>

    <div class="hot-link">
      热门搜索:
      <!--      查询参数传参-->
      <!--      <router-link to="/search?key=发现歌单">发现歌单</router-link>-->
      <!--      <router-link to="/search?key=我的歌单">我的歌单</router-link>-->
      <!--      <router-link to="/search?key=朋友歌单">朋友歌单</router-link>-->
      <!--      动态路由传参-->
      <router-link to="/search/发现歌单">发现歌单</router-link>
      <router-link to="/search/我的歌单">我的歌单</router-link>
      <router-link to="/search/朋友歌单">朋友歌单</router-link>

    </div>
  </div>
</template>

<script>
export default {
  name: "HomeComponent",
  data() {
    return {
      inpValue: ""
    }
  },
  methods: {
    goSearch() {
      //1.通过路径的方式跳转
      //(1) this.$router.push("路由路径")(常用)
      //this.$router.push('路由路径?参数名=参数值')
      // this.$router.push("/search")
      // this.$router.push(`/search?key=${this.inValue}`)

      //(2)this.$router.push({ (完整写法,更适合传参)
      //     path:'路由路径'
      //     query:{
      //      参数名:参数值,
      //      参数名:参数值
      //     }
      // })
      /*this.$router.push({
        path:"/search",
        query:{
          key:this.inpValue
        }
      })*/

      //  2.通过命名路由的方式跳转(在index.js文件中需要给路由起名字)(适合长路径-层级比较深)
      /* this.$router.push({
         name:'路由名'
       })*/
      this.$router.push({
        name: 'search',
        /*query: {
          key: this.inpValue
        },*/
        params: {
          words: this.inpValue
        }

      })
    }

  }

}
</script>

<style scoped>
.logo-box {
  height: 150px;
  background: url('@/assets/logo.jpg') no-repeat center;
}

.search-box {
  display: flex;
  justify-content: center;
}
</style>

25.5.6 Search.vue

<template>
  <div class="search">
    <!--  查询参数传参-->
    <!--  <p>搜索关键字:{{$route.query.key}}</p>-->
    <!--  动态路由传参-->
    <p>搜索关键字:{{ $route.params.words }}</p>
<!--    <p>搜索关键字:{{ $route.query.key}}</p>-->
    <p>搜索结果:</p>
    <ul>
      <li>..............</li>
      <li>..............</li>
      <li>..............</li>
      <li>..............</li>
      <li>..............</li>
      <li>..............</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "SearchComponent",
  created() {
    //  在created中,获取路由参数,this.$route.query.参数名 获取查询参数
    //  查询参数传参
    //   console.log(this.$route.query.key);

    //  在created中,获取路由参数,this.$route.params.参数名 获取动态路由参数
    //  动态路由传参
    console.log(this.$route.params.words)
  }
}
</script>

<style scoped>
.search {
  width: 400px;
  height: 240px;
  padding: 0 20px;
}
</style>

网站公告

今日签到

点亮在社区的每一天
去签到