路由传参

202 阅读4分钟

路由传参

跳转路由时 可以给路由对应的组件内传参

声明式导航

router-link 上的to属性,语法格式

/path?参数名=值
/path/值  ------需要路由对象提前配置   path:'/path/:参数名'

对应的页面组件接收传递过来的值

$route.query.参数名
$route.params.参数名

router/index.js

// 3 创建vue路由规则
const routes = [
  {
    path: '/',
    redirect: '/list', //重定向到  /home
  },
  {
    path: '/list',
    component: () => import('../views/List'),
  },
  {
    path: '/part',
    component: () => import('../views/Part'),
  },
  {
    path: '/detail/:name',
    component: () => import('../views/Detail'),
  },
  {
    path: '*',
    component: () => import('../views/NotFound'),
  },
]

List.vue

<template>
  <div>
    <router-link to="/part?name=小川">朋友--小川</router-link>
    <router-link to="/detail/小妞">朋友--小妞</router-link>
    <router-link :to="'/part?name=' + n1">朋友--{{ n1 }}</router-link>
    <router-link :to="'/detail/' + n1">朋友--{{ n1 }}</router-link>
  </div>
</template>
<script>
export default {
  data() {
    return {
      n1: '花姐',
      n2: '露露',
    }
  },
}
</script>

Part.vue

<template>
  <div>
    <p>关注明星</p>
    {{ $route.query.name }}
    <hr />
    {{ name }}
  </div>
</template><script>
export default {
  data() {
    return {
      name: '',
    }
  },
  created() {
    // 创建完成  第一次操作data中数据  执行一次
    this.name = this.$route.query.name
    console.log(this.name)
  },
}
</script>

Detail.vue

<template>
  <div>
    detail
    {{ $route.params.name }}
    <hr />
    {{ name }}
  </div>
</template><script>
export default {
  data() {
    return {
      name: '',
    }
  },
  created() {
    this.name = this.$route.params.name
  },
}
</script>

编程式导航

语法:

query/params 任选一个

this.$router.push({
    path:"路由路径",
    name:"路由名",
    query:{
        "参数名":"值"
    },
    params:{
        "参数名":"值"
    }
})

List.vue

<template>
  <div>
    <router-link to="/part?name=小川">朋友--小川</router-link>
    <router-link to="/detail/小妞">朋友--小妞</router-link>
    <router-link :to="'/part?name=' + n1">朋友--{{ n1 }}</router-link>
    <router-link :to="'/detail/' + n1">朋友--{{ n1 }}</router-link>
​
    <hr />
    <span @click="oneFn">朋友--小川</span>
    <span @click="twoFn">朋友--小妞</span>
    <span>朋友--{{ n1 }}</span>
    <span>朋友--{{ n1 }}</span>
  </div>
</template><script>
export default {
  data() {
    return {
      n1: '花姐',
      n2: '露露',
    }
  },
  methods: {
    oneFn() {
      this.$router.push({
        path: '/part',
        query: {
          // name: '小川',
          name: this.n2,
        },
      })
    },
    twoFn() {
      // path会自动的忽略params
      // this.$router.push({
      //   name: 'detail',
      //   params: {
      //     name: '小妞',
      //   },
      // })
      this.$router.push('/detail/' + this.n1)
    },
  },
}
</script>

路由守卫

router.vuejs.org/zh/guide/ad…

ue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。

全局前置守卫

需求:在跳转路由前,判断用户是否登录,登录了才能跳转到“我的音乐“页面,未登录弹窗提示

在路由对象上使用固定的方法 beforeEach

// 1 在路由对象上使用固定的方法 beforeEach
/* 
路由跳转"之前" 先执行这里,决定是否跳转
router.beforeEach((to,from ,next)=>{
to  要跳转到的路由 (路由对象信息)  目标
from 从哪里跳转的路由(路由对象信息)  来源
next  函数体, next() 才会让路由正常的跳转切换,  next(false)在原地停留  next("路由路径") 强制修改到另一个路由路径上
不调用next 页面留在原地
})


*/
// 在跳转路由前,判断用户是否登录,登录了才能跳转到“part“页面,未登录弹窗提示
const isLogin = false //登陆状态 (未登陆)
router.beforeEach((to, from, next) => {
  // console.log(to)
  // console.log(from)
  if (to.path === '/part' && isLogin === true) {
    alert('请登陆')
    next(false)
  } else {
    next() //正常放行
  }
})

Vant组件库

vant-contrib.gitee.io/vant/v2/#/z…

vant 轻量、可靠的移动端 Vue 组件库

安装

yarn add vant@latest-v2 -S

导入所有的组件

main.js中导入

// 导入所有的组件
import Vant from 'vant'
import 'vant/lib/index.css'

Vue.use(Vant)

使用组件

<van-button type="primary">主要按钮</van-button>
    <van-button type="info">信息按钮</van-button>
    <van-button type="default">默认按钮</van-button>
    <van-button type="warning">警告按钮</van-button>
    <van-button type="danger">危险按钮</van-button>

手动按需引入

只引入使用的组件

在不使用插件的情况下,可以手动引入需要的组件。---每一个组件中引入

import Button from 'vant/lib/button';
import 'vant/lib/button/style';

注册 --使用

<template>
  <div>
    <van-button type="primary">主要按钮</van-button>
    <van-button type="info">信息按钮</van-button>
    <van-button type="default">默认按钮</van-button>
    <van-button type="warning">警告按钮</van-button>
    <van-button type="danger">危险按钮</van-button>
  </div>
</template>

<script>
import Button from 'vant/lib/button'
import 'vant/lib/button/style'
export default {
  components: {
    // VanButton: Button,
    [Button.name]: Button,
  },
}
</script>

自动按需引入组件

babel-plugin-import 是一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式。

安装插件

yarn add babel-plugin-import -D

babel.config.js配置,重新启动项目

module.exports = {
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant']
  ]
};

组件中使用

<template>
  <div>
    <van-button type="primary">主要按钮</van-button>
    <van-button type="info">信息按钮</van-button>
    <van-button type="default">默认按钮</van-button>
    <van-button type="warning">警告按钮</van-button>
    <van-button type="danger">危险按钮</van-button>
    <van-icon name="chat-o" />
    <van-icon name="https://b.yzcdn.cn/vant/icon-demo-1126.png" />
  </div>
</template>

<script>
export default {}
</script>

<style scoped></style>

案例

路由配置

二级路由

组件

  • Layout.vue ---总的框架
  • List.vue ----商品列表
  • Search.vue -----商品搜索
  • My.vue-----我的信息

配置路由

const routes = [
  {
    path: '/',
    redirect: '/list',
    component: () => import('../views/Layout'),
    children: [
      {
        path: 'list',
        component: () => import('../views/List'),
      },
      {
        path: 'search',
        component: () => import('../views/Search'),
      },
      {
        path: 'my',
        component: () => import('../views/My'),
      },
    ],
  },
  {
    path: '*',
    component: () => import('../views/NotFound'),
  },
]

底部封装

  • 创建MyTabBar.vue组件
<template>
  <van-tabbar v-model="active" route>
    <van-tabbar-item icon="home-o" to="/list">商品列表</van-tabbar-item>
    <van-tabbar-item icon="search" to="/search">商品搜索</van-tabbar-item>
    <van-tabbar-item icon="friends-o" to="/my">我的信息</van-tabbar-item>
  </van-tabbar>
</template>

<script>
export default {
  data() {
    return {
      active: 0,
    }
  },
}
</script>

顶部封装

  • 创建MyHead.vue组件

    <template>
      <div class="head">TabBar案例</div>
    </template>
    
    <script>
    export default {}
    </script>
    
    <style scoped>
    .head {
      height: 50px;
      line-height: 50px;
      background-color: blue;
      text-align: center;
      color: white;
    }
    </style>
    

商品列表

  • 封装MyTable.vue ===标签和样式
  • axios 在MyGoodList.vue请求数据回来
  • 请求地址www.escook.cn/api/goods
  • 传入MyTable.vue 中循环数据显示

axios 在MyGoodList.vue请求数据回来

  • 下载axios

    yarn add axios
    
  • MyGoodList.vue

    <template>
      <div>
        <my-table :list="list"></my-table>
      </div>
    </template>
    
    <script>
    import axios from 'axios'
    import MyTable from './MyTable.vue'
    export default {
      components: {
        MyTable,
      },
      data() {
        return {
          list: [],
        }
      },
      created() {
        // axios({
        //   url: 'https://www.escook.cn/api/goods',
        // }).then((res) => {
        //   let {
        //     data: { data: result },
        //   } = res
        //   console.log(result)
        // })
        this.getDate()
      },
      methods: {
        async getDate() {
          let {
            data: { data: result },
          } = await axios({ url: 'https://www.escook.cn/api/goods' })
          console.log(result)
          this.list = result
        },
      },
    }
    </script>
    
  • MyTable.vue

    <template>
      <table class="table">
        <thead>
          <tr>
            <th>#</th>
            <th>名称</th>
            <th>价格</th>
            <th>标签</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(item, index) in list">
            <td>{{ item.id }}</td>
            <td>{{ item.goods_name }}</td>
            <td>{{ item.goods_price }}</td>
            <td>{{ item.tags }}</td>
            <td>
              <van-button type="primary">删除</van-button>
            </td>
          </tr>
        </tbody>
      </table>
    </template>
    
    <script>
    export default {
      props: {
        list: Array,
      },
    }
    </script>
    
    <style scoped>
    .table {
      width: 100%;
      margin: 20px auto;
      border: 1px solid #333;
      border-collapse: collapse;
    }
    td,
    th {
      border: 1px solid #333;
      height: 30px;
    }
    </style>
    

商品表格--插槽

使用插槽技术,和作用域插槽技术,给MyTable.vue组件,自定义列标题,自定义表格内容

需求:允许用户自定义表个头和表格单元格内容

  • 把MyTable.vue里准备slot
  • 使用MyTable组件时传入具体标签

步骤:

  • 提高组件==复用性和灵活性 ==,把表格列标题thead部分预留slot ,设置name属性
  • 使用MyTable.vue时,传入列标题标签
  • 表格内容td部分也可以让组件使用者自定义,也给tbody预留slot 和name属性
  • 使用插槽需要用到插槽内的item对象上的数据,作用域插槽

MyTable.vue

<template>
  <table class="table">
    <thead>
      <tr>
        <!-- <th>#</th>
        <th>名称</th>
        <th>价格</th>
        <th>标签</th>
        <th>操作</th> -->
        <slot name="header"></slot>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(item, index) in list">
        <!-- <td>{{ item.id }}</td>
        <td>{{ item.goods_name }}</td>
        <td>{{ item.goods_price }}</td>
        <td>{{ item.tags }}</td>
        <td>
          <van-button type="primary">删除</van-button>
        </td> -->
        <slot name="body" :row="item" :index="index"></slot>
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  props: {
    list: Array,
  },
}
</script>

MyGoodList.vue

<template>
  <div>
    <my-table :list="list">
      <template #header>
        <th>#</th>
        <th>名称</th>
        <th>价格</th>
        <th>标签</th>
        <th>操作</th>
      </template>
      <template #body="{ row, index }">
        <td>{{ row.id }}</td>
        <td>{{ row.goods_name }}</td>
        <td>{{ row.goods_price }}</td>
        <td>{{ row.tags }}</td>
        <td>
          <van-button type="primary">删除</van-button>
        </td>
      </template>
    </my-table>
  </div>
</template>

商品表格tags

<td>
          <van-tag v-for="(str, ind) in row.tags" :key="ind" type="primary">{{
            str
          }}</van-tag>
        </td>

\