vue-cli
vue-cli 安装
npm install -g @vue/cli
如果你的安装过慢或者无法安装则推荐使用cnpm安装 也就是淘宝镜像安装
npm install -g cnpm -registry=http://registry.npm.taobao.org
cnpm install -g @vue/cli
Vue-cli cli到底是什么呢?
Command-Line Interface 命令行界面 俗称脚手架
npm是什么呢?
Node Package Manager
是一个node包管理和分发的工具,已经成为非官方发布的node模块(包)的标准
详情请看node的笔记
cnpm又是什么呢?
淘宝定制的cnpm命令工具
拉取2.X的模板
npm install ‐g @vue/cli 如果使用这个命令安装cli 安装的是vue‐cli4.3.1
但是我们现在可能还需要cli2的模板,那么我们就还需要在这个基础之上将cli2的模板 拉取下来
使用下面命令拉取2.X的模板
npm install -g @vie/cli-init
安装vue-cli的时候经常会出现错误:
要查看的是是否使用的是管理员身份进行的cmd运行
npm clean cache -force
将我们在电脑系统中之前安装的一些配置进行清除
C:\Users\an\AppData\Roaming\npm-cache
npm-cache将这个文件夹手动删除也可以
cli2
如何创建一个vue-cli2的项目
在实际开发中,你创建的项目目录中不要有中文目录
通过cli2项目初始化命令来创建:
vue init webpack XXX //xxx表示创建项目文件的名字
在创建时需要配置很多的选项
Project name : 项目名字 一般和开始创建的项目文件夹名字相同
Project description : 项目描述
Author : 作者 默认 C:\Users\an.gitconfig 中的名字和邮箱
Vue build :
选择Vue发布时的两个版本
-
runtime-compiler
-
runtime-only 在实际开发中经常使用的版本 因为这个体积比较小,运行效率比 较高
Install vue-router : 是否安装vue路由 暂时不安装
use ESLint to lint your code : 代码规范
当选择y时,需要选择对应的代码规范:
- 直接选择标准规范
set up unit tests : 是否安装单元检测 几乎都是选择n
setup e2e tests with Nightwatch : 表示是否使用nightwatch进行端到端的测 试,也不需要,直接n
yes use NPM
cli2中的目录结构
build和config目录都是存放关于webpack配置文件
node_modules目录存放需要依赖的node的包
src目录: 所写的源文件,以后你要写代码的地方
static目录; 存放一些静态资源,这里面保存的所有内容会原封不动的打包到dist文件 夹里面
gitkeep 表示static文件夹中不管有没有内容都要进行一步复制操作
cli4
Vue-cli3以上都是基于webpack4开发的
vue-cli3以上设计原理:" 0配置 " 直接将build和config文件夹移出掉
vue-cli3以上提功了 vue ui命令 可视化配置,更加的人性化
移除了static文件夹,新增了一个public文件夹,将index.html扔进了这个文件夹中 cli4的目录结构
vue create XXX //XXX表示项目名字
进行配置
先无视第一项(我的个人配置,后面会讲到);一般有两项:
default:默认配置(只有babel和eslint)
Manually select features:手动配置
一般做项目默认配置是不够的,我们选第二项。
下一步
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IcNzmnQo-1627789946292)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20201028224410122.png)]
按照自己想要的配置,仅供参考
选择vue的版本
Choose a version of Vue.js that you want to start the project with
选2.X
下一步
询问是否将配置放在package.json文件中。推荐选第一项In dedicated config files
,创建新的配置文件。
下一步
询问是否将以上配置保存为预配置,也就是刚第一步选择配置时我的“Jsxj-preset”。这个根据自己意愿,预配置对以后创建项目来说还是方便点的
y 或 n随自己喜好
下一步就进行创建了,创建完就可以开始写代码了,删除没有用一些vue的默认配置组件
就可以自己写需要的组件了
npm run serve启动服务
cli4小案例
路由Router
认识路由
交换机与路由器的配置
路由就是网络工程专业里面的术语
路由就是通过互联网把信息从源地址传输到目的地的活动
路由大家可能不是很熟悉,但是路由器是不是都知道啊?
路由器提供了两种机制; 路由和转送
-
路由是决定数据包从来源到目的地的路径
-
转送是将输入端的数据转移到合适的输出端
路由中有一个非常重要的东西:路由表
路由表:本质上就是一个映射表
后端路由和前端路由
面试题: 什么是前端渲染? 什么是后端渲染?
1.最早期 前端 html+css 后端渲染: php jsp等
网页在服务端就已经加载好了,后端只是将加载好的html-css发给了用户
后端路由: 后端来处理url和页面之间的映射关系,这就是后端路由
缺点:后端的开发人员压力大,工作量非常繁重。html和java的代码以及数据都混合到一起,这样也不利于维护
2.ajax 前后端分离: 后端只负责数据,不负责任何的界面内容
前端来渲染页面
3.单页面富应用阶段 SPA :
主要特点就是在前后端分离的基础上加入了前端路由
每一个网站只有一个HTML,并且改变url页面不会刷新
实现前端路由:
前端来处理url和页面之间的映射关系,这就是前端路由
如何实现改变url但页面不刷新呢?
可以有两种手段:
-
location中的hash
this.$router.hash(“路径”)
-
history模式 pushState
this.$router.push(“路径”)
vue-router基本使用
vue-router是基于路由和组件的,路由是设置访问路径,将路径和组件来进行一一映 射
安装
npm install vue-router --save
使用
在src文件夹下创建router文件夹,在里面创建index.js用来配置路由
配置:
- 导入路由对象
- 调用 Vue.use(VueRouter)
- 创建路由实例
- 在路由实例中传入路由的映射配置
- 在Vue实例中挂载路由实例
index.js
//配置路由相关信息
import Vue from 'vue'
import VueRouter from 'vue-router'
//通过use()来引用插件
Vue.use(VueRouter)
//创建VueRouter对象
const routes = [
]
//配置路由与组件之间的关系
const router = new VueRouter({
routes
})
//将router导出
export default router
main.js
import Vue from 'vue'
import App from './App.vue'
//导入router
import router from './router/index'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
配置映射关系:
1.创建多个对应的组件
2.配置路由映射
index.js中添加
//导入组件
import Home from '../components/Home'
import About from '../components/About'
//配置路由映射
const routes = [
{
path : '/home',
component : Home
},
{
path : '/about',
component : About
}
]
使用路由
to属性: 用于指定跳转的路径
tag属性:通过这个属性修改解析之后的标签样式
replace属性: 不会保留历史记录
active-class属性:会将处于活跃状态的路由添加一个 router-link-active 的 类名修改成我们想要的名字
使用router-link标签进行跳转
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
使用<router‐view>标签来渲染要加载的组件
<router‐view></router‐view>
在路由实例中设置 mode:‘history’ 实现转换成history模式 ,地址没有#号
//配置路由与组件之间的关系
const router = new VueRouter({
routes,
mode : "history"
})
配置路由重定向,可以实现当页面一加载的时候指向另一个路由位置
//创建VueRouter对象
const routes = [
//配置路由重定向,可以实现当页面一加载的时候指向另一个路由位置
{
// ‘/’表示刚打开url时进入的页面
path:"/",
redirect : '/home'
},
{
path : '/home',
component : Home
},
{
path : '/about',
component : About
}
]
除了 其他方式跳转:
<template>
<div>
<button @click="homeClick">首页</button>
<button @click="about">关于</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
methods:{
homeClick(){
this.$router.push("home")
},
about(){
this.$router.push("about")
}
}
}
</script>
<style>
</style>
动态路由: 在某些情况下,url的路径可能不是固定的,这时候我们就需要用到动态路 由 (路径传参)
path(路径配置)
{
path : '/user/:userId',
component : User
}
App.vue中使用第二中方式跳转
<template>
<div>
<button @click="homeClick">首页</button>
<button @click="about">关于</button>
<button @click="user">用户</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
methods:{
homeClick(){
this.$router.push("hoeme")
},
about(){
this.$router.push("abeout")
},
user(){
this.$router.push("user/"+123)
}
}
}
</script>
<style>
</style>
User:然后在对应的组件中设置计算属性
这里是 r o u t e 不 是 route不是 route不是router
$route代表当前活跃的路由
$router代表全部路由
<template>
<div>
qqqq
{{id}}
</div>
</template>
<script>
export default {
name: "User",
computed :{
id(){
//获取数据
return this.$route.params.userId
}
}
}
</script>
<style scoped>
</style>
路由懒加载
好处:当执行到当前路由时,再去导入vue文件,更加高效
const routes = [
{
path : '/home',
component : ()=>import('../components/Home')
}
]
vue-router的嵌套路由
比如 是在Home页面 希望通过 /home/message /home/news去访问一些内容 一个路径要映射一个组件,这两个路径也需要映射两个不同的组件
二个步骤:
创建对应的子组件,并且在路由映射表中配置对应的子路由 children属性配置
const routes = [
{
path : '/home',
component : Home,
children:[
{
path: "message",
//导入子组件
component: () => import("../components/homeChildren/Message")
}
]
}
]
App.vue
<template>
<div>
<button @click="message">消息</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
methods:{
message(){
this.$router.push("/home/message")
}
}
}
</script>
<style>
</style>
Home.vue中加入标签
<template>
<div>
qqqq
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
vue-router导航守卫
主要目的就是监听从什么位置跳转到了什么位置
全局前置守卫
如果我们希望每一个页面都有自己的title,就需要用到全局守卫
在路由表的配置中添加对应的meta属性 添加title:“首页”
{
path: "/about",
component: ABout,
meta : {
title : "关于"
}
}
在路由的index.js中 全局配置全局前置守卫
从名字全局前置守卫不难理解,它是全局的,即对 整个单页应用(SPA) 中的所有路由都生效,所以当定义了全局的前置守卫,在进入每一个路由之前都会调用这个回调,那么如果你在回调中对路由的跳转条件判断出错,简单点就是死循环…因为你遗漏了某种路由跳转的情况,守卫会一直执行。所以在使用全局前置守卫的时候一定要判断清楚可能会出现的路由跳转的情况。
//设置一个全局导航守卫
router.beforeEach(function (to,from,next) {
document.title = to.matched[0].meta
next();
})
to 表示即将要进入的路由对象
from 表示即将要离开的路由对象
next 调用该方法,才能进入下一个钩子
例子:
router.beforeEach((to, from, next) => {
//开启懒加载
iView.LoadingBar.start()
//获取token
const token = getToken()
if (!token && to.name !== LOGIN_PAGE_NAME) {
// 未登录且要跳转的页面不是登录页
next({
name: LOGIN_PAGE_NAME // 跳转到登录页
})
} else if (!token && to.name === LOGIN_PAGE_NAME) {
// 未登陆且要跳转的页面是登录页
next() // 跳转
} else if (token && to.name === LOGIN_PAGE_NAME) {
// 已登录且要跳转的页面是登录页
next({
name: 'home' // 跳转到homeName页
})
}
})
至于代码中的令牌token就是通过cookie存储的一个键值对
全局后置守卫(钩子)
router.afterEach((to,from) => {
//执行的代码
})
理解了全局前置守卫,那么全局后置守卫也就那么一回事。全局后置守卫是整个单页应用中每一次路由跳转后都会执行其中的回调。所以多用于路由跳转后的相应页面操作,并不像全局前置守卫那样会在回调中进行页面的重定向或跳转。
应用场景前面以及提了就是对跳转后的页面进行例如滚动条回调0 0 位置、更新页面title、懒加载结束等等
router.afterEach((to, from) => {
setTitle(to, router.app)
iView.LoadingBar.finish()
window.scrollTo(0,0)
})
keep-alive
Vue实例中内置的一个组件
当我们每一次返回之前的组件页面时,都是重新创建的新组建
将 router-view 被keep-alive 包起来,这时候所有的路径匹配的视图组件都会被缓存,但是当前组件里面的二级路由的内容不会被缓存
如果让二级路由里面的内容也跟着一起保存呢?
将二级路由的重定向取消掉
在二级路由的父组件中设置path的数据保存默认路径
父组件中添加两个钩子函数,这两个钩子函数只有在keep-alive保存之后才会有效 当前组件处于活跃状态时,就会执行
activated(){
}
beforeRouteLeave(){
}
keep-alive 添加一些属性
exclude=“User,About” 这里面的组件不会被keep-alive缓存
<keep-alive exclude="User,About">
<router-view></router-view>
</keep-alive>
Vue-X
Vuex是一个什么呢?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
它采用“集中式存储管理”应用的所有组件的状态,并以相应的规则保证状态以一种 可预测的方式发生变化
Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
状态管理又是什么呢?
就是我们在多个组件中可能需要用到一些共有的数据或者变量,那么我们可以使用一 个共有的对象来进行集中式的存储
将所有这些公用的内容放入到这个对象中,不管哪一个组件想要使用这里面的内容, 都可以给提供 响应式
状态管理都会管理什么数据呢?
单页面的管理状态
Vuex 是一个插件
Vuex 第一步还是安装
npm install vuex --save
或
yarn add vuex --save
Vuex基本使用
Vuex是做什么 什么是状态管理 哪些状态需要管理 单页面的状态管理 Vuex的最基本的 使用 state
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LhsL5gc8-1627789946295)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20201105185601832.png)]
创建一个文件夹 store
在该文件夹下创建一个index.js
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
//安装插件
Vue.use(Vuex)
//创建对象
var store = new Vuex.Store({
//存放数据
state:{},
//存放同步方法
mutations:{},
//存放异步方法
actions:{},
//计算属性
getters:{},
//模板分离
modules:{}
})
//导入store
export default store
main.js
import Vue from 'vue'
import App from './App.vue'
//在main.js中挂载
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App),
}).$mount('#app')
如何修改state中的数据
需要用到mutations这个属性了 来定义一些方法实现state状态的改变
但是我们该如何使用这里面的方法呢?
this.$store.commit(‘add’) 来调用mutations里面的add方法
Vuex里面的五个核心概念:
state:保存公共的状态 单一状态树
我们在Vuex中只会创建一个store仓库,不需要创建多个
mutations:
Vuex中的state状态唯一的变更方式:提交到mutations里面来变更
主要分成两部分:
事件类型type
回调函数,这里函数中第一个参数就是我们的state内容
this.$store.commit(‘add’) 来调用mutations里面的add方法
Vue中提供了另一种提交方式:
this.$store.commit({
type:'add',
user
})
在mutations里面接收到的值是一个对象类型的值,里面保存两个属性分别是: type user
store/index.js
var store = new Vuex.store({
//存放数据
state:{
count : 0
},
//存放同步方法
mutations:{
add(state,value){
state.count = value;
}
},
//存放异步方法
actions:{},
//计算属性
getters:{},
//模板分离
modules:{}
})
app.vue
<template>
<div id="app">
<!--拿到vuex中state的值-->
{{$store.state.count}}
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
created(){
//调用mutations中的add方法,并传入数据
this.$store.commit('add',2)
}
}
</script>
<style>
</style>
Mutations响应式的规则
在state里面的内容都是被加入到响应式中的
在state的数据中,每一条数据都会有一个Dep Dep就是一个监听者
这个数据如果想要是响应式,那么就必须在state中来进行定义
Vue.set(要更改的数据源,要更改的具体数据,重新赋的值)
Mutations所有定义的方法都是同步的方法,这里面不允许写异步操作
getters:
类似于组件中的计算属性
当我们某一个数据需要经过一系列的变化后才能用,那么我们就需要用到getters
actions:和mutations很像,一个解决同步一个解决异步
解决异步操作
modules:
划分模块
拿到模块中的state状态:
$store.state.模块名.状态数据
拿到模块中的mutations状态:
this.$store.commit(‘模块中的方法’) 所有模块中的方法名字不能重名
拿到模块中的getters中的计算属性:
unt = value;
}
},
//存放异步方法
actions:{},
//计算属性
getters:{},
//模板分离
modules:{}
})
app.vue
```vue
<template>
<div id="app">
<!--拿到vuex中state的值-->
{{$store.state.count}}
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
created(){
//调用mutations中的add方法,并传入数据
this.$store.commit('add',2)
}
}
</script>
<style>
</style>
Mutations响应式的规则
在state里面的内容都是被加入到响应式中的
在state的数据中,每一条数据都会有一个Dep Dep就是一个监听者
这个数据如果想要是响应式,那么就必须在state中来进行定义
Vue.set(要更改的数据源,要更改的具体数据,重新赋的值)
Mutations所有定义的方法都是同步的方法,这里面不允许写异步操作
getters:
类似于组件中的计算属性
当我们某一个数据需要经过一系列的变化后才能用,那么我们就需要用到getters
actions:和mutations很像,一个解决同步一个解决异步
解决异步操作
modules:
划分模块
拿到模块中的state状态:
$store.state.模块名.状态数据
拿到模块中的mutations状态:
this.$store.commit(‘模块中的方法’) 所有模块中的方法名字不能重名
拿到模块中的getters中的计算属性:
this.$store.getters.计算属性名字