1.问题背景:
vue-router 默认是hash模式,使用url的hash来模拟一个完整的url,当url改变的时候,页面不会重新加 载。但是如果我们不想hash这种以#号结尾的路径时候的话,我们可以使用路由的history的模式。比如如 下网址:使用hash模式的话,那么访问变成 http://localhost:8080/bank/page/count/#/ 这样的访问,
如果路由使用 history的话,那么访问的路径变成 如下:http://localhost:8080/bank/page/count 这样的 了;不过history的这种模式需要后台配置支持。比如:当我们进行项目的主页的时候,一切正常,可以访 问,但是当我们刷新页面或者直接访问路径的时候就会返回404,那是因为在history模式下,只是动态的通过js操作window.history来改变浏览器地址栏里的路径,并没有发起http请求,但是当我直接在浏览器里输入这 个地址的时候,就一定要对服务器发起http请求,但是这个目标在服务器上又不存在,所以会返回404怎么解 决呢?我们现在可以把所有请求都转发到 http://localhost:8080/bank/page/index.html上就可以了
解决方案一:在nginx的配置文件中修改
```php
location /{
root /data/nginx/html;
index index.html index.htm;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
break;
}
}
```
解决方案二:vue.js官方教程里提到的
```javascript
server {
listen 8081;#默认端口是80,如果端口没被占用可以不用修改
server_name myapp.com;
root D:/vue/my_app/dist;#vue项目的打包后的dist
location / {
try_files $uri $uri/ @router;#需要指向下面的@router否则会出现vue的路由在nginx中刷新出现404
index index.html index.htm;
}
#对应上面的@router,主要原因是路由的路径资源并不是一个真实的路径,所以无法找到具体的文件
#因此需要rewrite到index.html中,然后交给路由在处理请求资源
location @router {
rewrite ^.*$ /index.html last;
}
#.......其他部分省略
}
```
2.子组件能不能修改父组件传递过来的数据*
原因:
在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop
给子组件下发数据,子组件通过事件给父组件发送消息。Prop
是单向绑定的:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子
组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解
解决办法:
将要更改的值,传递给父组件,在父组件中更改,再传递给子组件
步骤:
先将值传递给子组件,子组件 props 接收并使用,然后通过 $emit
广播一个事件给父组件,并将值一并传递,父组件
@子组件广播过来的事件,并定义一个方法,在该方法中,改变传递过来的值,父组件又会将
值传递给子组件,这样就形成了一个闭环,问题得以解决
3.路由导航守卫
1.概念
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。通俗点讲就是一个拦截器。
2.分类
全局守卫
beforeEach、beforeResolve、afterEach(在路由实例对象注册使用)
路由守卫
beforeEnter(在路由配置项中项定义)
组件守卫
beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave(在组件属性中定义)
钩子的参数
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(false)===不写 终止执行
next()===next(true)继续执行
next(path)跳转到目标路径
全局守卫详解 在路由的index.js页面设置
全局前置守卫(beforeEach)
```javascript
// 全局前置守卫 确保要调用 next 方法,否则钩子就不会被 resolved。
router.beforeEach((to, from, next) => {
var username = 'miofly'
if (username === 'miofly') { // 用户是miofly才进入下一个页面
console.log('beforeEach全局前置守卫被调用')
next() // 进行管道中的下一个钩子,必须调用
} else { // 如果不是回到主页
// 如果直接写next('/indexs'),会造成死循环(dead loop)
// 这是因为,执行next('/indexs')这个跳转,会触发beforeEach方法,
// 这时候,就会造成,又执行next('/indexs') 这样的死循环,所以还要再加一层判断
if (to.path === '/indexs') {
next()
} else {
next('/indexs')
}
}
})
```
全局解析守卫(beforeResolve)
```javascript
// 全局解析守卫
// 和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
router.beforeResolve((to, from, next) => {
console.log('beforeResolve全局解析守卫被调用')
next()
})
```
全局后置钩子(afterEach)
```javascript
// 全局后置钩子
2. // 可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
3. router.afterEach((to, from) => {
4. console.log('afterEach全局后置钩子被调用')
5. })
```
单个路由守卫(在配置路由的时候设置)
```
{
path: '/test',
component: testIndex,
beforeEnter: (to, from, next) => {
console.log('beforeEnter路由独享的守卫被调用')
next()
},
}
```
组件内部守卫
```javascript
mounted () { // 这不是组件守卫,留作测试用
console.log('mounted被调用了')
},
beforeRouteEnter (to, from, next) {
console.log('beforeRouteEnter被调用:在渲染该组件的对应路由被 confirm 前调用')
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this` 因为当守卫执行前,组件实例还没被创建
// 可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
next(vm => {
// 通过 `vm` 访问组件实例
console.log(vm)
})
},
// beforeRouteEnter 是支持给 next 传递回调的唯一守卫。
// 对于 beforeRouteUpdate 和 beforeRouteLeave 来说,this 已经可用了,所以不支持传递回调,因为没有必要了。
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
console.log('beforeRouteUpdate被调用:在当前路由改变,但是该组件被复用时调用')
next()
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
const answer = window.confirm('是否确认离开当前页面')
if (answer) {
console.log('beforeRouteLeave被调用:导航离开该组件的对应路由时调用')
next()
} else {
next(false)
}
}
```