1、vue-cli ( 脚手架 )
脚手架是基于webpack,用于快速构建项目的工具。
首先需要在电脑安装脚手架的环境。
npm install -g @vue/cli
1) 创建vue项目eslint有什么用
用来检查你的代码是否符合指定的规范
2) babel
Vue Babel是一个用于将Vue.js代码转换为可在旧版浏览器中运行的工具
3) 保留所需的功能
4) 项目创建成功
5)怎么利用脚手架(vue-cli)构建项目、怎么进行开发项目
步骤:
一种方式:
一、在工作目录中,打开cmd 或其他命令面板
二、输入 vue create project_name 回车
三、选择项目使用的功能(版本、预处理语言、插件等)
四、按照提示进行回车确认(按一下空格按键表示选择、按两下表示取消)
五、一切就绪,就等待生成项目
六、项目生成后,就可以进行开发
cd project_name 切换目录
npm run serve 运行项目
npm run build 打包项目
另外一种方式:
在面板终端输入
vue ui
在浏览器弹出可视化操作界面
根据提示就可以创建项目、运行项目....
2、Vue-Router 路由
1)URL(路径) -------> Component(组件)
是什么?
是一种管理URL和组件的语法(管理路径和组件的系统)。
2)什么作用?
可以根据不同的URL渲染不同的组件,显示不同的界面。
可以做导航跳转
vue-router 是做页面导航的插件。
可以利用vue-cli工具把这个插件下载到项目中
3)安装vue-router
在vue-cli构建过程进行选择
src
|-------router
|--------- index.js
4)基本步骤:
1) 定义组件A
2)配置路由,配置URL和组件A的关系
3)利用router-link组件的to属性做导航跳转
4)通过访问URL就可以访问组件(渲染组件),在router-view组件出口渲染
// 路由配置
const routes = [
{
path: '/',// 路径 URL
name: 'home', // 路由名称
component: HomeView // 组件
},
{
path: '/about',
name: 'about',
// 组件懒加载 (需要访问URL才加载组件)
component: () => import('../views/AboutView.vue')
},
{
path: "/my",
name: 'my',
// component: ()=> import('../views/MyView.vue')
component: ()=> import('@/views/MyView.vue')
}
]
设置router-link的样式
./router/index.js
// 创建路由实例
const router = new VueRouter({
// 挂载配置
routes,
// 设置链接标签激活状态的样式(点击)
// linkActiveClass: 'active',
// linkExactActiveClass: 'active'
// URL有两种模式
// 历史模式:不带# history
// 哈希模式:锚点 #
mode: "hash"
})
router-link
<nav>
<!-- 设置链接标签激活状态的样式(点击) -->
<!-- active-class="" -->
<!-- exact-active-class="" -->
<!-- 可以设置标签名称 a标签 div标签 -->
<!-- tag="div" -->
<router-link to="/" exact-active-class="active" tag="div">
<i class="icon-home"></i>
<span class="text">主页</span>
</router-link>
<router-link to="/about" exact-active-class="active" tag="div">
<i class="icon-about"></i>
<span>关于</span>
</router-link>
<router-link to="/my" exact-active-class="active" tag="div">
<i class="icon-my"></i>
<span>我的</span>
</router-link>
</nav>
设置URL路径
./router/index.js
// 创建路由实例
const router = new VueRouter({
// 挂载配置
routes,
// URL有两种模式
// 历史模式:不带# history
// 哈希模式:#
mode: "hash"
})
5)路由传参数
<div id="app">
<!-- router-view: 路由出口组件(窗口) -->
<!-- <router-view/> -->
<router-view></router-view>
<!-- router-link: 链接组件 -->
<footer class="app-footer">
<nav>
<!-- 设置链接标签激活状态的样式(点击) -->
<!-- active-class="" -->
<!-- exact-active-class="" -->
<!-- 可以设置标签名称 a标签 div标签 -->
<!-- tag="div" -->
<router-link to="/" exact-active-class="active">
<i class="icon-home"></i>
<span class="text">主页</span>
</router-link>
<router-link to="/about" exact-active-class="active">
<i class="icon-about"></i>
<span>关于</span>
</router-link>
<router-link :to="`/my`" active-class="active">
<i class="icon-my"></i>
<span>我的</span>
</router-link>
<!-- <router-link :to="`/my?token=aaa111`" exact-active-class="active">
<i class="icon-my"></i>
<span>我的</span>
</router-link> -->
<!-- <router-link :to="{path: '/my',query: {i:10,j:20} }" exact-active-class="active">
<i class="icon-my"></i>
<span>我的</span>
</router-link> -->
<!-- <router-link :to="{name: 'my', params:{a:100,b:200} }" exact-active-class="active">
<i class="icon-my"></i>
<span>我的</span>
</router-link> -->
<!-- 动态匹配规则 -->
<!-- <router-link :to="`/my/1/2`" exact-active-class="active">
<i class="icon-my"></i>
<span>我的</span>
</router-link> -->
</nav>
</footer>
</div>
MyView.vue
<script>
export default {
// 初始化
created() {
// 1) 路径: :to="`/my/1/2`"
// 获取路径的参数 (路由匹配规则) 刷新页面参数的值不会消失
// this.$route: 路由对象
console.log(this.$route);
// 解构赋值
// let {x,y} = this.$route.params;
// console.log({x,y});// {x: '1', y: '2'}
// 2) 路径: :to="{name: 'my', params:{a:100,b:200} }"
// let {a,b} = this.$route.params;
// console.log({a,b});
// 通过name这种方式传递参数,刷新页面参数的值会消失
// 3) 路径: :to="{path: '/my',query: {i:10,j:20} }"
let { i, j } = this.$route.query;
console.log({ i, j });
// 通过path这种方式传递参数,刷新页面参数的值不会消失
},
// 挂载程序了
mounted(){
// 获取路由
// console.log(this.$route)
// 设置网页标题
document.title = this.$route.meta.title;
}
};
</script>
6)编程式的导航
<template>
<div id="app">
<!-- 不使用router-link组件能不能做导航? 答案: 能 -->
<button class="btn" @click="jumpTask">任务</button>
<button class="btn" @click="jumpDetail">详情</button>
<!-- 路由出口 -->
<router-view/>
</div>
</template>
<script>
export default {
// 设置方法
methods: {
// 跳转任务
jumpTask(){
// 编程式导航
this.$router.push({path: '/task'});
},
jumpDetail(){
// 跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
// this.$router.replace({path: '/detail'})
this.$router.push({path: '/detail'});
}
}
}
</script>
编程式导航
用户重复点击、重复调用push replace 方 而产生的错误
解决方案:
1) main.js
// 避免用户重复点击 重复调用push replace 方法 而产生的错误日志
// 复制以下代码(cli)
import VueRouter from 'vue-router'
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function (location) {
return originalPush.call(this, location).catch(err => { })
};
2) demo.vue
// 编程式导航
// 避免用户重复点击 重复调用push replace 方法 而产生的错误日志
// .catch(err=>{}
otherFunc() {
this.$router.push({
path: '/'
}).catch(err=>{});
},
homeFunc() {
this.$router.replace({
path: '/home'
}).catch(err=>{});
},
7)路由守卫
通过URL访问组件的过程中,可以设置回调函数做拦截,判断是否允许该URL访问组件。
这个过程出现的回调函数,我们叫做路由守卫钩子函数。
路由守卫有3种:
全局路由守卫 在./router/index.js 文件中,通过router这个实例对象调用的回调函数
独享路由守卫 在./router/index.js 文件中,在路由配置中编写 {path,component, 钩子}
组件内置路由守卫 在组件中编写的守卫,例如在Home.vue 文件中编写的
场景:
例如,浏览某宝商城App,看上一件物品,想加入购物车。在点击“加入购物车”的时候就做判断,做拦截,程序会判断用户是否为登录状态,
如果没有登录,就跳转登录页面; 如果已经登录,就跳转购物车页面
每个守卫方法接收三个参数:
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
1、全局路由守卫 在./router/index.js 文件中,通过router这个实例对象调用的回调函数
// to: Route: 即将要进入的目标 路由对象
// from: Route: 当前导航正要离开的路由
// next: Function: 一定要调用该方法来 resolve 这个钩子。
// 全局前置路由守卫
router.beforeEach((to, from, next) => {
// console.log("即将进入的目标:", to)
// console.log("正要离开的路由:", from)
// 做拦截,不让访问about组件
// if(to.name == 'about') {
// // 不允许访问
// next(false);
// }
// else {
// next();
// }
// 判断访问的对象是否携带auto_toke属性值
if(to.meta.auto_token === 'xxxx' || to.name == 'login' || to.name == 'payment') {
next()
}
else {
// 给用户反馈
if(confirm('您要跳转登录页面?')){
next('/login')
}
else {
next(false)
}
}
// console.log("11111")
})
// 全局后置路由守卫(和其他守卫不一样,没有next参数,没有拦截)
// router.afterEach((to, from) => {
// console.log("to:",to)
// console.log("from:",from)
// console.log("22222")
// })
2、独享路由守卫 在./router/index.js 文件中,在路由配置中编写 {path,component, 钩子}
{
path: '/payment',
name: 'payment',
component: () => import('../views/PaymentView.vue'),
// 路由独享守卫(局部守卫)
beforeEnter: (to, from, next) => {
// console.log("即将进入的目标:", to)
// console.log("正要离开的路由:", from)
if(from.meta.id === 10010) {
next(false)
}
else {
next();
}
}
},
3、组件内置路由守卫 在组件中编写的守卫,例如在Home.vue 文件中编写的
export default {
name: "OrderView",
// 组件内置路由守卫
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
if(confirm("您要支付订单吗?")){
next();
console.log("访问之前 确定访问");
}
else {
next(false);
console.log("访问之前 取消访问");
}
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
console.log("URL更新");
next();
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
if(confirm("您要离开吗?")){
next();
console.log("离开");
}
else {
next(false);
console.log("不离开");
}
},
};