Vue值Router(路由)2

在路由中,我们除了可以在 <router-link>中写入a标签来定义导航链接,还可以借助 Router实例方法,通过编程代码来实现

编程式导航

两种代码样式

声明式编程式
<router-link :to=”…”>router.push(…)
因为Vue实例内部,我们可以通过$router访问 Router的实例,所以Router的实例方法push可以用 this.$router.push(…)调用

router.push使用方法

一、router.push的参数为字符串路径

router.push方法是参数可以是一个字符串路径

router.push('user')
router.push('/user')
router.push('user') router.push('/user')router.push('user') router.push('/user')

下面详细说明上面两种写法的不同,主要是跳转后 url 的变化不同:

原 urllocalhost:8080localhost:8080/home
router.push(‘user’)
跳转后的 url
localhost:8080/userlocalhost:8080/home/user
router.push(‘/user’)
跳转后的 url
localhost:8080/userlocalhost:8080/user

因为 / 意味着匹配根路由,所以 '/user' 这样的写法不管原路径 localhost:8080/?? 中的 ?? 是什么,跳转后 url 都会变为 localhost:8080/user

二、router.push 的参数为描述地址的对象

router.push 方法的参数可以是一个描述地址的对象:

// 对象
// 这种写法和字符串类型的参数一样
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

只提供 path 值的参数和字符串类型的参数是一样的。这里就不再说了。我们主要看一下后两种写法。

  1. { name: 'user', params: { userId: '123' }}
  • 对应的命名路由为: { path:'user/:userId', name:'user' }
  • 跳转后 url:localhost:8080/user/123
  • 取参数:$route.params.userId
  1. { path: 'register', query: { plan: 'private' }}
  • 对应的路由为: { path:'register' }
  • 跳转后 url:localhost:8080/register?plan=private
  • 取参数:$route.query.plan

小结一下参数传递的对应规则:

  • name 对应 params,路径形式:user/123;
  • path 对应 query,路径形式:user?id=123;

如果使用 path 进行页面跳转的时候,写 params 进行传参会被忽略:

// params 会被忽
router.push({ path: 'user', params: { userId: '123' }})

可以换成下面的写法:

router.push({ path: 'user/123'})

同样的规则也适用于 router-link 组件的 to 属性。

页面跳转后如何获取参数

例如工程

// $route
{
  // 路由名称
  name: "user",
  meta: {},
  // 路由path
  path: "/user/123",
  // 网页位置指定标识符
  hash: "#abc",
  // window.location.search
  query: {name: "userName"},
  // 路径参数 user/:userId
  params: {userId: "123"},
  fullPath: "/user/123?name=userName#abc"
}

我们以http://localhost:8080/user/123?name=userName#abc 地址来访问

可以通过 $route.query$route.params$route.hash来获取参数

重定向与别名

别名

别名指两个名字指向一个路由:

const routes: [
  // 定义 alias 属性
  { path: '/a', alias: '/b', component: A }
];

即访问 /a 和 /b 都会渲染 A

重定向

重定向指的是路由跳转,如 /a 重定向到 /b ,即访问 /a 时,url自动跳转到 /b 并匹配 /b路由

const routes: [
  // 定义 redirect 属性,将 /a 重定向到 /b
  { path: '/a', redirect: '/b' }
]

监听路由

当头部标签切换时,路径也会发生变化,我们需要监听路径变化来改变标签样式,或者加载对应的内容。

我们利用 watch 和 $router 来完成监听

watch: {
  $route(to,from){
    console.log(to, from);
  }
}

// 或者
watch: {
  $route: {
    handler: function(to,from) {
      console.log(to,from);
    },
    // 深度观察监听
    deep: true
  }
},

定义点击事件:

<script>
export default {
  methods: {
    // 点击 tab 时会执行 changeTab 方法
    changeTab(type) {
      // 使用 Router 实例方法改变路径参数
      this.$router.push({ query: { type: type } });
    }
  }
};
</script>

更新标签样式

<script>
export default {
  watch: {
    $route(to, from) {
      // 路由变化了就执行更新样式的方法
      this.updateTab();
      console.log(to, from);
    }
  },
  methods: {
    changeTab(type) {
      this.$router.push({ query: { type: type } });
    },
    // 更新样式的方法
    updateTab() {
      this.tabList.map(menu => {
        menu.active = menu.type === this.$route.query.type;
      });
    }
  }
};
</script>

因为我们此时默认路径开始没有参数type,所以默认选择第一个,但当路径默认有初始参数,我们就需要马上更新样式

<script>
export default {
  methods: {
    // ...
    updateTab() {
      if (!this.$route.query.type) {
        return;
      }
      this.tabList.map(tab => {
        tab.active = tab.type === this.$route.query.type;
      })
    }
  }
};
</script>

网络请求 async与 await

在js中,我们进行网络请求都是通过:

fetch(
  'https://www.fastmock.site/mock/b73a1b9229212a9a3749e046b1e70285/f4/f4-11-1-1'
)
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });

因为fetch是一个promise对象,无等待,所以对返回数据进行操作时要添加大量then。

所以我们使用 async(异步)和await(等待异步)

使用async前我们需要声明一个异步function

async function asyncFn() {
  return {
    "company": "优课达",
    "slogan": "学的比别人好一点"
  };
}

const result = asyncFn();
console.log(result);

async返回的也是一个promise对象,但其与fetch区别在有着await

await 用于等待一个异步方法执行的完成,它会阻塞后面的代码,等着 Promise 对象 resolve *,然后得到 resolve 的值,作为 await 表达式的运算结果:

async function getAsyncFn() {
  const result = await asyncFn();
  console.log(result);
}

getAsyncFn();

注意的是 await只能出现在 async函数中

多个请求并发执行

如要是多个请求并发执行 可以使用 Promise.all

async function asyncFn1() {
  return "优课达";
}

async function asyncFn2() {
  return "学的比别人好一点";
}

async function getAsyncFn() {
  const result = await Promise.all([asyncFn1(), asyncFn2()]);
  console.log(result);
}

getAsyncFn();

请求参数:

<script>
export default {
  data: function() {
    return {
      courseList: []
    };
  },
  async mounted() {
    // 在生命周期 mounted 中调用获取课程信息的方法
    await this.queryAllCourse();
  },
  methods: {
    // 在 methods 对象中定义一个 async 异步函数
    async queryAllCourse() {
      // 在 fetch 中传入接口地址
      const res = await fetch('https://www.fastmock.site/mock/2c5613db3f13a5c02f552c9bb7e6620b/f5/api/queryallcourse');
      // 将文本体解析为 JSON 格式的promise对象
      const myJson = await res.json();
      // 获取返回数据中的 data 赋值给 courseList
      this.courseList = myJson.data;
    }
  }
}
</script>

传递参数:

<script>
export default {
  data: function() {
    return {
      course: []
    };
  },
  async mounted() {
    await this.getCourse();
  },
  methods: {
    async getCourse() {
      // 从路径中获取课程 id
      const courseId = this.$route.params.courseId
      // 在接口地址后传入参数 id
      const res = await fetch('https://www.fastmock.site/mock/2c5613db3f13a5c02f552c9bb7e6620b/f5/api/getcourse?id=${' + courseId + '}');
      const myJson = await res.json();
      this.course = myJson.data;
    }
  }
}
</script>