【Vue的环境搭建】
1.【掌握】node和npm的说明
1.1什么是node和npm
Node:是JavaScript的运行时环境。Node并不是一个新的语言,只是js的一个环境,同样的比如:tomcat。Node为js提供了更强大的操作方式,如:在浏览器中,js是无法操作文件的,而node提供了文件操作。在浏览器中,js无法写服务接口,node提供了后端代码编写的功能(写后台、操作数据库)。尽管如此,Node依然是个前端技术,并不会真正的使用node去写后端代码,node更多的是给前端项目做配置,如:跨域代理。
Npm:npm是node提供的一个包管理工具,类似于maven。通过npm去安装依赖包,就不需要在页面上使用script标签引入了。 前端也有依赖
命令:-g(globle)全局安装,任何项目都可以用。--save-dev开发环境安装,不会打包到生产。生产安装(默认)
大前端工程: 人家可以使用node js 开发数据接口, 但是nodejs 的速度很差.
1.2 node的下载
http://nodejs.cn/
1.3 Node的安装(重点)
压缩包:
解压就可以了
1.4 配置node的环境变量
1.4.1 配置
直接使用:
就可以了.是否配置缓存和全局设置文件夹自己决定
或者下面也行:
1.4.2 测试环境变量
1.5 npm镜像加速配置(记得安装)
1.5.1 第一种方案
npm config set registry https://registry.npm.taobao.org
1.5.2 第二种方案
安装nrm 可以不写-g -g是全局安装
npm i nrm -g
查看所有镜像
nrm ls
切换淘宝镜像
nrm use taobao
备注:是否配置全局全局安装目录和缓存日志目录自己决定 我这里是一个项目
npm i
1.5.3 npm卸载插件
npm uninstall 组件名 -g
- vue脚手架
2.1 什么是vue-cli
vue脚手架指的是vue-cli,它是一个专门为单页面应用快速搭建繁杂的脚手架,它可以轻松的创建新的应用程序而且可用于自动生成vue和webpack的项目模板。
vue-cli是有Vue提供的一个官方cli,专门为单页面应用快速搭建繁杂的脚手架。它是用于自动生成vue.js+webpack的项目模板。
2.2 vue-cli的安装
1.傻瓜式安装node:
官网下载:https://nodejs.org/zh-cn/
2.安装cnpm: 可以不安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
3.安装vue最新脚手架:
切换淘宝国内镜像否则非常慢
npm config set registry https://registry.npm.taobao.org/
cnpm install -g @vue/cli
可以用:vue --version 命令,查看当前安装版本
4.卸载vue脚手架
npm uninstall vue-cli -g
注:如果2、3步报错,清除缓存后重新走2、3步
npm cache clean --force
出错的解决方案:如果出现Unexpected token .. in JSON at position ....
解决手段1:
切换成淘宝的国内镜像:
npm config set registry https://registry.npm.taobao.org/
查看是否切换成功:
npm config get registry
强制清除npm缓存:
npm cache clean --force
再执行安装npm:
npm install -g npm
再次执行安装vue命令:
npm install -g @vue/cli
解决手段2:
删除根目录下package-lock.json文件,重新安装vue
官网地址:https://cli.vuejs.org/zh/guide/installation.html
参考官网的操作
- Idea工具的vue操作
在idea的工具栏中使用:Terminal测试node环境
查看node版本
node -version
查看npm版本
npm -v
问题:
本地安装好Node.js后,在IDEA中的Terminal工具中执行npm命令发现不能识别,而在cmd中则能识别,说明环境变量配置的是没问题的。
File——>Settings——>Tools——>Terminal,发现Shell Path配置的不是本地的cmd地址,修改为本地cmd路径后,保存重启Intellij IDEA即可。
- 创建Vue工程
创建项目需要注意:项目名不能有中文,不支持驼峰(含有大写字母)
命令:vue create 项目名
创建中:
Package.json
语法检查:默认安装过vue插件,使用es6
- 使用vue ui创建项目-命令
5.1 命令启动图型化界面
5.2 界面效果
5.3 界面选择创建
5.4 输入相关配置
5.5 下一步预设
5.6 下一步选择安装
5.7 下一步
5.8 项目仪表盘
5.9 npm命令中--save,--save-dev,-S,-D的区别
5.9.1 package.json里dependencies和devDependencies
dependencies是生产时的依赖:比如:vue, axios,echarts,element-ui,vant等这些项目打包后也依旧就能够用到的重要依赖;
devDependencies是开发时的依赖:比如:eslint,prettier代码美化和检查,sass-loader css预编译,babel es6转es5,uglifyjs-webpack-plugin js代码压缩,image-webpack-loader 图片压缩 等这些loder , plugin, babel, webpack类的辅助开发或只在打包阶段使用的;不会再生产中使用的依赖我们要放在devDependencies模块里面;
5.9.2 –save,–save -dev,-S,-D 命令的区别
--save 等同于-S(是前者的缩写):安装包信息将放入到dependencies(生产阶段的依赖,是项目运行时的依赖,程序上线后仍然需要依赖)
--save-dev等价于-D(也是前者的缩写):安装包信息将放入到 devDependencies(开发阶段的依赖,是我们在开发过程中需要的依赖)
- 组件
6.1 什么是组件
组件的出现,是为了拆分Vue的代码块,不同的组件划分不同的功能模块,以后我们需要某个功能时,就直接调用对应的组件即可
模块化:模块化是从代码的角度去分析的,方便代码分层开发,保证每个模块职责单一
组件:组件化是从界面的角度去划分的,如:分页组件、轮播、颜色选择、文件上传等抽象,是把公共的东西像的东西抽出来(好处:复用,公共的,缺点:代码的可读性直线下降)
这里没有介绍非单文件组件,非单文件组件的实际应用意义不大,且脚手架方式的组件命名方式和非单文件组件有不同,我们注解学习脚手架版的单文件组件
变量名说明:(组件的使用规范)
按java的开发思想,变量名往往是驼峰规则 myComponent my-component
在vue脚手架中定义组件名称必须是多个单词,
两种命名方式:
1、大驼峰 MyComponent
2、-:连接符号: my-component
组件分为:根组件(App.vue)、一般组件、路由组件
6.2 Vue组件的使用
Vue中使用组件的三大步骤:
一、定义组件(创建组件)
二、注册组件
三、使用组件(写组件标签)
6.2.1 定义组件
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
- el不要写,为什么?
最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。- data必须写成函数,为什么?
避免组件被复用时,数据存在引用关系。
格式:
<template>
//HTML代码
</template>
<script>
//VueComponent对象
export default {
name:'',
data(){
return {
key:值,
}
},
methods: {
}
...
}
</script>
<style>
//css样式
</style>
二、如何注册组件?
1.局部注册:靠new Vue的时候传入components选项
2.全局注册:靠Vue.component('组件名',组件)
//全局注册组件
Vue.component('hello',hello)
//创建vm
new Vue({
el:'#root',
data:{
msg:'你好啊!'
},
//第二步:注册组件(局部注册)
components:{
school,
student
}
})
三、编写组件标签:
<组件名></组件名>
6.2.2 组件的使用
组件的结构:
所有的组件都需要注册在App.vue中,App.vue被称为根组件
Vue对象直接绑定根组件
Student.vue
<template>
<div>
<h2>学生姓名:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
</template>
<script>
export default {
name:'MyStudent',
data(){
return {
name:'大郎',
age:18
}
}
}
</script>
<style scoped>
</style>
School.vue
<template>
<div class="demo">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我提示学校名</button>
</div>
</template>
<script>
export default {
name:'MySchool',
data(){
return {
name:'学校',
address:'上海'
}
},
methods: {
showName(){
alert(this.name)
}
}
}
</script>
<style scoped>
</style>
App.vue
<template>
<div>
<MySchool></MySchool>
<MyStudent></MyStudent>
</div>
</template>
<script>
import MySchool from './components/School'
import MyStudent from "./components/Student"
export default {
name: 'App',
components:{
MySchool:MySchool,
MyStudent:MyStudent
}
}
</script>
<style scoped>
</style>
main.js
// 引入Vue
import Vue from 'vue'
// 引入app组件,它是所有组件的父组件
import App from './App.vue'
// 关闭vue生产提示
Vue.config.productionTip = false
// 创建vue实例对象 -- vm
new Vue({
el:"#app",
render: h => h(App),//render函数 渲染的是哪个.vue组件 这个组件就是根组件
})
6.2.3 组件嵌套
把Student嵌套到School中,成为School的子标签
- 路由
vue-router:vue 的一个插件库,专门用来实现 SPA 应用
7.1 什么是SPA应用
- 单页 Web 应用(single page web application,SPA)。
- 整个应用只有一个完整的页面。
- 点击页面中的导航链接不会刷新页面,只会做页面的局部更新。
- 数据需要通过 ajax 请求获取。
7.2 什么是路由
- 一个路由就是一组映射关系(key - value)
- key 为路径, value 可能是 function 或 component
路由的分类:
- 后端路由: 例如:@RequestMapping
- 理解:value 是 function, 用于处理客户端提交的请求。
- 工作过程:服务器接收到一个请求时, 根据请求路径找到匹配的函数来处理请求, 返回响应数据。
- 前端路由: router
- 理解:value 是 component,用于展示页面内容。
- 工作过程:当浏览器的路径改变时, 对应的组件就会显示。
参考美团生活:https://sh.meituan.com/shenghuo
7.3 安装路由插件
命令:npm i vue-router
注意:
有的人安装的时候会报错,意思是说vue-router版本不对
2022年以后vue-router的默认版本为4版本,只能在vue3中使用
Vue2中我们需要使用vue-router的3版本
命令:npm i vue-router@3 -g -d
7.4 路由的使用
7.4.1 路由的格式
//引入VueRouter
import VueRouter from 'vue-router'
//引入路由组件
import 组件1 from '组件路径'
import 组件2 from '组件路径'
import 子组件1 from '组件路径'
//创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
routes:[
// path中的/ 指当前路由是一级路由 直接跟在#后面
{
name:"路由名",//可以根据路由名称来找到路由 可以不写
path:'/路由组件的路径',
component:组件1,
children:[//路由可以有多个子路由 子路由的格式不变
{
name:"路由名",//可以根据路由名称来找到路由 可以不写
path:'子路由组件的路径',//子路由的路径不要写/ vue编译器会自动加上/ 自己写会出错
component:子组件1
}
]
},
{
path:'/路由组件的路径',
component:组件2
}
]
})
7.4.2 配置路由器
在src下创建router文件夹,创建index.js,把路由器的设置都写在这
router/index.js
//引入VueRouter
import VueRouter from 'vue-router'
//引入路由组件
import Login from '../components/Login'
import Reg from '../components/Reg'
//创建router实例对象,去管理一组一组的路由规则
export default new VueRouter({
routes:[
{
path:'/login',
component:Login
},
{
path:'/reg',
component:Reg
}
]
})
Login.vue
<template>
<div>
<center>
<h1>登录</h1>
<form>
账号:<input type="text" v-model="userCode"><br/><br/>
密码:<input type="password" v-model="userPwd"><br/><br/>
<button>提交</button>
</form>
</center>
</div>
</template>
<script>
export default {
name: "MyLogin",//注意名字要符合规则 大驼峰或者用-连接 否则会报错
data() {
return {
userCode: "",
userPwd: ""
}
}
}
</script>
<style scoped>
</style>
Reg.vue
<template>
<div>
<center>
<h1>注册</h1>
<form>
账号:<input type="text" v-model="userCode"><br/><br/>
密码:<input type="password" v-model="userPwd"><br/><br/>
性别:<input type="radio" v-model="sex" value="男">男
<input type="radio" v-model="sex" value="女">女<br/><br/>
地址:<select v-model="address">
<option value="shanghai">上海</option>
<option value="北京">北京</option>
<option value="天津">天津</option>
</select>
<br/><br/>
其他信息:
<textarea v-model="other"></textarea> <br/><br/>
<input type="checkbox" v-model="agree">阅读并接受<a href="http://www.atguigu.com">《用户协议》</a>
<button>提交</button>
</form>
</center>
</div>
</template>
<script>
export default {
name: "MyReg",
data(){
return {
userCode:"",
userPwd:"",
sex:"",
address:"",
other:"",
agree:""
}
}
}
</script>
<style scoped>
</style>
App.vue
<template>
<div id="root">
<div>
<h1>欢迎使用用户系统</h1>
<!-- router-link:会自动变成a标签 to:跳转路由的路径 可以写成对象-->
<router-link to="/login">登录</router-link>
<router-link to="/reg">注册</router-link>
</div>
<hr/>
<div>
<!-- 路组件展示的位置 -->
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
#root {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
//引入router模块
import router from "./router/index"
/*
把路由插件注册到vue对象中 可以写在router/index.js中 两者必须写一个
引入路由器插件
import VueRouter from "vue-router";
让vue对象能够是有路由器
Vue.use(VueRouter)*/
new Vue({
el:"#app",
router:router,//挂载到vue对象中
//render函数 渲染的是哪个.vue组件 这个组件就是根组件
render: h => h(App),
})
细节:
1、设置默认路径
2、地址栏不想要#
7.4.3 多级路由
Login.vue
<template>
<div>
<center>
<h1>
<router-link to="/login/defaultLogin">账号密码登录</router-link>
<router-link to="/login/messageLogin">手机短信登录</router-link>
</h1>
<hr/>
<router-view></router-view>
</center>
</div>
</template>
<script>
export default {
name: "MyLogin",//注意名字要符合规则 大驼峰或者用-连接 否则会报错
}
</script>
<style scoped>
</style>
DefaultLogin.vue
<template>
<div>
<center>
<h1>账号密码登录</h1>
<form>
账号:<input type="text" v-model="userCode"><br/><br/>
密码:<input type="password" v-model="userPwd"><br/><br/>
<button>提交</button>
</form>
</center>
</div>
</template>
<script>
export default {
name: "DefaultLogin",//注意名字要符合规则 大驼峰或者用-连接 否则会报错
data() {
return {
userCode: "",
userPwd: ""
}
}
}
</script>
<style scoped>
</style>
MessageLogin.vue
<template>
<div>
<center>
<h1>手机短信登录</h1>
<form>
手机号:<input type="text" v-model="userCode"><br/><br/>
验证码:<input type="password" v-model="userPwd"><br/><br/>
<button>提交</button>
</form>
</center>
</div>
</template>
<script>
export default {
name: "MessageLogin",//注意名字要符合规则 大驼峰或者用-连接 否则会报错
data() {
return {
userCode: "",
userPwd: ""
}
}
}
</script>
<style scoped>
</style>
router/index.js
//引入VueRouter
import VueRouter from 'vue-router'
//引入路由组件
import Login from '../components/Login'
import Reg from '../components/Reg'
//引入vue 把路由器注册到vue对象上
import Vue from "vue";
//让vue对象能够是有路由器
Vue.use(VueRouter)
//创建router实例对象,去管理一组一组的路由规则
export default new VueRouter({
routes:[
{
path:"/",
redirect:"/login"
},
{
path:'/login',
component:Login,
children:[
{
path:"/login",
redirect:"defaultLogin"
},
{
path:"messageLogin",//二级路由不要写/ vue会自动拼装二级路径/
component:()=>import("../components/MessageLogin")
},
{
path:"defaultLogin",
component:()=>import("../components/DefaultLogin")
}
]
},
{
path:'/reg',
component:Reg
}
],
mode:"history"
})
7.4.4 路由组件的命名
路由器可以通过路由组件的名字进行配置
路由器的配置项中有name属性:给当前路由起名字
7.4.5 路由守卫
路由守卫是一组可以监听路由变化并控制路由跳转的函数,可以用来在路由跳转前/后对页面进行权限验证、状态拦截等操作,从而增强页面交互的安全性和可控性。
路由守卫包括全局守卫、单个路由独享的守卫和组件内守卫三种类型。
全局守卫
全局守卫是指能够监听所有路由跳转事件的函数,可以在每次路由变化时执行一些操作,比如打印日志、检查用户身份等。
全局守卫包括以下三个函数:
beforeEach(to, from, next):在路由跳转前执行,可以用来进行权限验证和状态拦截等操作。其中 to 表示要跳转的目标路由对象,from 表示当前的路由对象,next 是一个必须调用的函数,用于控制页面跳转。
如果 next() 被调用,就会立即跳转到目标路由,如果 next(false) 被调用,那么页面将停留在当前路由,如果 next('/') 被调用,那么会跳转到指定的路由地址。
beforeResolve(to, from, next):在路由跳转完成前执行,可以在组件渲染前获取数据。该守卫只在需要在进入被确认的所有钩子解析完之后执行。
afterEach(to, from):在路由跳转完成后执行,可以用来处理页面跳转完成后的事件,比如滚动位置的恢复、销毁页面组件等。
格式:路由器对象名.beforeEach((to,from,next)=>{})
注意事项:全局守卫必须主动对外声明路由器对象
前置路由守卫可以拦截指定组件,
组件过多时可以使用:meta设置自定义标识
组件设置:
{
//这个组件的访问路径
path:"/login",
component:LoginDemo,
children:[
{
path:"codeLogin",
component:()=>import("../components/CodeLogin"),
meta:{isAuth:true}
},
{
name:"phoneLoginName",
path:"PhoneLogin",
component:()=>import("../components/PhoneLogin"),
}
]
},
前置路由守卫:
router1.beforeEach((to, from, next)=>{
console.log("前置路由守卫to:",to)
console.log("前置路由守卫from:",from)
console.log("前置路由守卫next:",next)
//可以根据to的name path来判断是否放行 组件较多使用meta来提供标识
if(to.meta.isAuth){
next();
}else{
next("/login");//强行去登录页面
}
})
后置路由守卫
afterEach( ) 全局后置守卫:初始化时执行、每次路由切换后执行
两个参数:to ,from,没有next参数,其他和全局前置守卫一样
router1.afterEach((to, from)=>{
console.log("后置路由守卫to:",to)
console.log("后置路由守卫from:",from)
this.title="我的vue工程"
})
独享路由守卫
含义:某一个路由独有的路由守卫,api 名字是 beforeEnter
单个路由独享的守卫是指只针对单个路由定义的函数,可以用来对该路由进行特殊的控制和操作。比全局守卫更细粒度。
beforeEnter(to, from, next):在路由跳转前执行,和全局前置守卫的用法一样,但是只对当前路由有效。
{
//这个组件的访问路径
path:"/login",
component:LoginDemo,
children:[
{
path:"codeLogin",
component:()=>import("../components/CodeLogin"),
meta:{isAuth:true},
beforeEnter:((to, from, next)=>{
console.log("独享路由守卫to:",to)
console.log("独享路由守卫from:",from)
console.log("独享路由守卫next:",next)
//可以根据to的name path来判断是否放行 组件较多使用meta来提供标识
if(to.meta.isAuth){
next();
}else{
next("/login");//强行去登录页面
}
})
},
独享路由守卫只有 beforeEnter ,没有 后置守卫
beforeEnter 和 全局后置守卫 可以同时使用,不冲突!
组件内路由守卫
组件内路由守卫,就是在组件内部编写代码,实现权限管理 ,如果组件里面有自己单独的权限逻辑,可以使用这两个路由守卫
进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) { },
离开守卫:通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) { }
<template>
<div>
我是User的内容
</div>
</template>
<script>
export default {
name:'UserDemo',
// 进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {
console.log("beforeRouteEnter被调用")
if(to.meta.isAuth){
if(localStorage.getItem('username') === "大郎"){
next()
}else{
alert('用户名不正确,没有权限查看!')
}
}else{
next()
}
},
//离开守卫:通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {
console.log("beforeRouteLeave被调用",to,from)
next()
}
}
</script>
<style scoped>
</style>
7.4.6 LocalStorage
使用LocalStorage进行本地存储可以很方便地存储用户相关的数据,比如访问记录、用户偏好设置等。
LocalStorage 是一种用于浏览器本地存储数据的技术,它可以让开发者将数据存储在用户的浏览器中,当用户重新打开页面时,这些数据依然可以被访问到。
在使用LocalStorage时需要注意以下几点:
1、存储的数据需要为字符串类型,如果存储的数据不是字符串类型,则需要使用JSON.stringify()将其转化为字符串类型。
2、获取LocalStorage时需要使用localStorage.getItem()方法进行获取, 如果获取的数据是字符串型的JSON数据,则可以使用JSON.parse()方法将其转换为JSON格式。
3、删除LocalStorage时需要使用localStorage.removeItem()方法进行删除。
// 存储数据到LocalStorage
localStorage.setItem('user', JSON.stringify({ username: '大郎', age: 20 }))
// 获取LocalStorage中存储的数据
const user = JSON.parse(localStorage.getItem('user'))
console.log(user)
// 删除LocalStorage中的数据
localStorage.removeItem('user')
注意LocalStorage的存储空间是有限的,因此不能将所有数据都存储在LocalStorage中,否则会影响程序的运行效率。建议按照实际需求选择合适的存储方式。
7.4.7 路由的跳转和传参
路由跳转有三种方式:
1、
:浏览器解析为a标签
2、this.$router.push:常用方式
3、this.$router.replace{path:”路由地址”,query:{key:value}}
7.4.7.1 this.$router.push()
不带参数跳转
// 不带参数,直接跳转页面
this.$router.push('/路由地址') 直接写路径
this.$router.push({path:'/路由地址}) 使用path属性
this.$router.push({name: '路由组件名' })使用name属性
push函数的参数有:name path query params
name和path不要共存,query和params不要共存
带参数跳转
<button @click=‘hChange()’>点击按钮跳转页面</button>
function hChange () {
this.$router.push({ path: '/page', query: { id: '001' } })
// 根据路由路径 + query 的方式跳转传参
this.$router.push({ name: 'page', query: { id: '001' } })
// 根据路由组件名称 + query 的方式跳转传参
this.$router.push({ name: 'page', params: { id: '001' } })
// 根据路由组件名称 + params 的方式跳转传参 只能使用name
}
组件接收参数
// 在html中接收参数
$route.query.id
$route.params.id
// 在script中接收参数
this.$route.query.id
this.$route.params.id
Message.vue
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<button @click="hChange(m)">{{m.title}}</button>
</li>
</ul>
<hr>
<router-view></router-view>
</div>
</template>
<script>
export default {
name:'MyMessage',
data() {
return {
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
},
methods:{
hChange(m){
console.log("m对象:",m)
this.$router.push({
name:"/message/detail",
query:{
id:m.id,
title:m.title
}
})
}
}
}
</script>
<style scoped>
</style>
Detail.vue
<template>
<ul>
<li>消息编号:{{$route.query.id}}</li>
<li>消息标题:{{$route.query.title}}</li>
</ul>
</template>
<script>
export default {
name:'MessageDetail',
mounted() {
console.log(this.$route)
}
}
</script>
params方式:restful风格的请求
注意:只能使用路由的名字
路由的地址需要使用占位符 :key
路由设置:
{
path:"/message",
component:()=>import("../components/Message"),
children:[
{
name:"MessageDetail",
path:'detail/:id/:title',//:key占位符 会把参数变成url的一部分
component:()=>import("../components/Detail")
}
]
},
Message.vue
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<button @click="hChange(m)">{{m.title}}</button>
<!-- <router-link to=""-->
</li>
</ul>
<hr>
<router-view></router-view>
</div>
</template>
<script>
export default {
name:'MyMessage',
data() {
return {
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
},
methods:{
hChange(m){
console.log("params方式m对象:",m)
this.$router.push({
name:'MessageDetail',//只能使用路由的名字
params:{
id:m.id,
title:m.title
}
})
}
}
}
</script>
<style scoped>
</style>
Detail.vue
<template>
<ul>
<li>消息编号:{{$route.params.id}}</li>
<li>消息标题:{{$route.params.title}}</li>
</ul>
</template>
<script>
export default {
name:'MessageDetail',
mounted() {
console.log(this.$route)
}
}
</script>
params 和 query 传参的区别:
1、params传参时,参数不会出现在url路径后面,但是刷新页面时param里面的数据会消失
2、query传参时,参数出现在url路径后面,刷新页面时query里面的数据不变
7.4.7.2 扩展
this.$router.push:
跳转到指定 url 路径,并向 history 栈中添加一个记录,点击后退会返回到上一个页面 ==>> 队列的方式(先进先出)
this.$router.replace:
跳转到指定 url 路径,但是 history 栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面) ==>> 栈的方式(先进后出)
this.$router.back:
请求(返回)上一个记录路由
this.$router.go:
向前或者向后跳转n个页面,n可为正整数或负整数
使用to的方案:
- Axios插件安装
命令:npm install axios -S -D
npm install -S [email protected]
加上@0.19.0 是指定版本号;不指定npm默认安装最新的版本;
在需要使用的地方引入axios对象import axios from axios
- 配置代理
vue单页应用项目开发时,避免不了要请求后端,这时通常就会出现跨域问题。
1、什么是跨域问题?
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都会导致跨域问题。即前端接口去调用不在同一个域内的后端服务器而产生的问题。
2、如何解决跨域问题?
有2种常用的解决方案:
1、后端设置允许跨域访问
2、前端通过代理进行访问后端
9.1 后端设置允许跨域访问
后端的跨域访问设置也是比较简单的,不同语言JAVA PHP Python Go的设置也大同小异。
例如:SpringMVC允许跨域的设置
1.使用的方式用@Controller和@CrossOrgin一起使用,可以实现跨域!
只有Spring版本从4.2开始才有跨域支持!
//某个方法支持跨域访问:在方法上增加@CrossOrigin注解
@RequestMapping("/crossDomain2.action")
@ResponseBody
@CrossOrigin
public String crossDomain2(HttpServletRequest req, HttpServletResponse res, String name){
return null;
}
整个Controller都支持跨域访问
//整个Controller都支持跨域访问,在类上面加上注解@CrossOrigin
@Controller
@CrossOrigin
public class TestController {
}
2.使用定义全局的跨域配置:可以通过实现WebMvcConfigurer并重写 addCorsMappings方法来实现跨域
3.使用过滤器方式
public class HeaderFilter implements Filter{
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse) res;
String originHeader = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", originHeader);
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "0");
response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("XDomainRequestAllowed","1");
response.setHeader("XDomainRequestAllowed","1");
chain.doFilter(request, response);
}
}
注意:但在生产环境下,为了安全起见,还是建议不要设置允许跨域访问,或者 限制允许跨域的IP
9.2 前端配置代理
代理服务器的主要思想是通过建立一个端口号和前端相同的代理服务器进行中转,从而解决跨域问题。因为代理服务器与前端处于同一个域中,不会产生跨域问题;而且代理服务器与服务器之间的通信是后端之间的通信,不会产生跨域问题。
原理:浏览器和服务器当:协议、ip、端口号有一个不一致,就是违背同源策略找一个和浏览器同源的服务器,让这个服务器帮我们代理给别的服务器发请求服务器之间不必遵守同源策略
vue-cli配置代理的两种方法:编写vue.config.js
9.2.1 方法一:简单代理配置
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,//对使用的JS 语法进行转译 不同版本使用不同
// 开启代理服务器,注意:这里的端口号写后端的端口号(方式一)
devServer: {
port: 4201,//前端服务器端口号
proxy: 'http://localhost:5000'
}
})
说明:
1、优点:配置简单,请求资源时直接发给前端(8080)即可
2、缺点:不能配置多个代理,不能灵活的控制请求是否走代理
3、工作方式:若按照上述配置代理,当请求了不存在的资源时,那么该请求就 会转发给服务器(有限匹配前端资源)
案例:
<template>
<div>
<button @click="getStudents">获取学生信息</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
name:'ShowStudent',
methods:{
getStudents(){
//注意:开启代理服务器后,get中的端口号要改为前端所在的端口号,即4201
axios.get('http://localhost:4201/students').then(
response => {
console.log('请求成功了',response.data)
},
error => {
console.log('请求失败了',error.message)
}
)
}
}
}
</script>
页面:
控制台结果:
9.2.2 方法二:多个代理配置
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,//对使用的JS 语法进行转译 不同版本使用不同
devServer: {
port: 4201,//前端服务器端口号
proxy: {
'/adminapi': {//当前代理服务器的名字
target: 'http://localhost:8180',//代理服务器指向的后台服务器地址
ws: true,//用于支持websocket
changeOrigin: true,// 用于控制请求头中的host值 代理欺骗 可以不写
pathRewrite: {'^/adminapi': ''} //重写路径,把所有路径中包含/adminapi的路径替换为空字符串
},
'/secondapi/': {
target: 'http://localhost:8185/',//其他服务器地址
ws: true,
changeOrigin: true,
pathRewrite: {'^/secondapi': ''}
}
}
}
})
说明:
1、优点:可以配置多个代理,并且可以灵活的控制请求是否走代理
2、缺点:配置略微繁琐,请求资源时必须加前缀。
案例:
<template>
<div>
<button @click="getStudents">获取学生信息</button>
<button @click="getCars">获取汽车信息</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
name:'Show',
methods:{
getStudents(){
//注意:多个代理,要加上前缀 /adminapi 指明使用哪个代理
axios.get('http://localhost:4201/adminapi/students').then(
response => {
console.log('请求成功了',response.data)
},
error => {
console.log('请求失败了',error.message)
}
)
},
getCars(){
//注意:多个代理,要加上前缀 /secondapi指明使用哪个代理
axios.get('http://localhost:4201/secondapi/cars').then(
response => {
console.log('请求成功了',response.data)
},
error => {
console.log('请求失败了',error.message)
}
)
},
},
}
</script>
页面效果:
控制台信息:
- 安装Element-ui
命令:npm i element-ui -s
最好加上参数 -s 安装到生产环境
10.1 Vue2完整引入Element-Ui
缺点:载入文件过大,速度会受影响
脚手架环境中创建项目的components文件夹添加一个组件【EleTest.vue】,把Element-Ui中的组件内容放入
<template>
<el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
<el-menu-item index="1">处理中心</el-menu-item>
<el-submenu index="2">
<template slot="title">我的工作台</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
<el-menu-item index="2-3">选项3</el-menu-item>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项1</el-menu-item>
<el-menu-item index="2-4-2">选项2</el-menu-item>
<el-menu-item index="2-4-3">选项3</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item index="3" disabled>消息中心</el-menu-item>
<el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
</el-menu>
</template>
<script>
export default {
name: "ElementTest",
data() {
return {
activeIndex: '1',
activeIndex2: '1'
};
},
methods: {
handleSelect(key, keyPath) {
console.log(key, keyPath);
}
}
}
</script>
<style scoped>
</style>
App.vue内容
<template>
<div>
<el-test></el-test>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import ElTest from "./components/ElementTest"
export default {
name: 'App',
components: {
HelloWorld,
ElTest
}
}
</script>
<style>
</style>
全局main.js
// 引入Vue
import Vue from 'vue'
// 引入app组件,它是所有组件的父组件
import App from './App.vue'
// ElementUI
import ElementUI from 'element-ui' //element-ui的全部组件
import 'element-ui/lib/theme-chalk/index.css'//element-ui的css
Vue.use(ElementUI) //使用elementUI
// 关闭vue生产提示
Vue.config.productionTip = false
// 创建vue实例对象 -- vm
new Vue({
el:"#app",
// 完成了这个功能:将APP组件放入窗口中
render: h => h(App),
})
10.2 案例:传统上左右页面
配合element实现上左右页面,核心在于用:default-active 属性动态的绑定当前激活菜单的路由路径,然后通过路由嵌套的方式跳转指定路由即可。
代码:
<template>
<div>
<el-container>
<el-aside width="240px">
<el-menu :default-active="$route.path" class="el-menu-vertical-demo" router>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>工厂设置</span>
</template>
<el-menu-item-group>
<el-menu-item index="/navigator/index">商户信息</el-menu-item>
<el-menu-item index="/navigatorTwo/index">推广团队</el-menu-item>
<el-menu-item index="/navigatorTherr/index">插件管理</el-menu-item>
<el-menu-item index="/navigatorFour/index">我的客户</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header>头部</el-header>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<style scoped>
.el-header {
background-color: #b3c0d1;
color: #333;
line-height: 60px;
height: 100%;
}
.el-aside {
background-color: #d3dce6;
color: #333;
height: 100vh;
}
.el-main {
background-color: #e9eef3;
color: #333;
}
</style>
router/index.js文件代码
import VueRouter from 'vue-router'
const routes = [{
path: '/',
component: () => import('../views/overall/index.vue'),
children: [
{
path: "/navigator/index",
component: () => import('../views/navigator/index.vue')
},
{
path: "/navigatortwo/index",
component: () => import('../views/navigatortwo/index.vue')
},
{
path: "/navigatorTherr/index",
component: () => import('../views/navigatorTherr/index.vue')
}, {
path: "/navigatorFour/index",
component: () => import('../views/navigatorFour/index.vue')
},
]
}]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
全局main.js
// 引入Vue
import Vue from 'vue'
// 引入app组件,它是所有组件的父组件
import App from './App.vue'
// ElementUI
import ElementUI from 'element-ui' //element-ui的全部组件
import 'element-ui/lib/theme-chalk/index.css'//element-ui的css
Vue.use(ElementUI) //使用elementUI
//引入router模块
import router from "./router"
/*把路由插件注册到vue对象中 可以写在router/index.js中 两者必须写一个
引入路由器插件*/
import VueRouter from "vue-router";
/*让vue对象能够是有路由器*/
Vue.use(VueRouter)
// 关闭vue生产提示
Vue.config.productionTip = false
// 创建vue实例对象 -- vm
new Vue({
el:"#app",
router:router,
// 完成了这个功能:将APP组件放入窗口中
render: h => h(App),
})
标签:Vue,name,vue,import,组件,router,脚手架,路由
From: https://www.cnblogs.com/llhcmbs/p/18364994