没用使用 name
特性,它将作为默认 slot
出现,父组件没有使用 slot
特性的元素与内容都将出现在这里。
如果没有指定默认的匿名 slot
, 父组件内多余的内容片段都将被抛弃.
上例最终渲染后的结果为:
<div id="app">
<div class="container">
<div class="header">
<h2>标题</h2>
</div>
<div class="main">
<p>正文内容</p>
<p>更多的正文内容</p>
</div>
<div class="footer">
<div>底部信息</div>
</div>
</div>
</div>
注:在组合使用组件时,内容分发API至关重要。
路由
一、怎么理解路由
就是跳转的机制 然后这个跳转的规则由程序员来指定
二、前端路由 后台路由
前端路由
:是由程序员来设置的页面跳转规则,由不同的路径显示不同的组件 但是前端路由的路径在后台服务器上是不存在的
后台的路由
:每个路由对应的是一个接口,也就是说后台的路由是在服务器上真实存在的,每个后台的路径都对应的一个接口数据
打个例子来说:
/bannerList 轮播的数据接口
/list 数据列表的接口
三、路由的原理
vue的路由分为两种:hash
路由 history
路由
hash路由
:
js原生事件 onhashchange()
当页面的hash
发生变化就会触发该事件
history路由
:
是利用h5新增的api
history堆栈
来实现的
js原生事件 ononpopstate()
来检测页面的路径变化 从而根据路径来显示不同的页面
四、路由的配置
vue中的路由默认
的为hash
路由
src->router->index.js
是我们的路由配置文件 所有的路由都会在这个文件中进行配置
怎么由hash模式变为历史模式
给router对象添加 mode:"history"
, 默认的是hash
模式
src->router->index.js文件
五、路由配置的步骤
一、新建对应路由的组件
二、配置路由规则
**`router->index.js`**
2.1、引入所有用到的组件
2.2、配置相应的规则
{
path:
name:
component:
}
2.3、给路径对应的组件找到显示的位置
是系统给我们提供的一个显示路径所对应组件的这么一个组件 可以直接使用
2.4、给路由的显示添加导航
是提供提供给我们路由导航的组件 可以直接使用 默认的情况下解析为a标签
更换标签 tag="标签名"
2.5、默认的路径在导航上添加router-link-active类
2.6、配置默认路径
{
path;“/”,
redirect:"路径"
}
三、二级路由的配置
哪个一级路由下配置二级路由
1、新建组件
2、配置规则
给要配置二级路由的一级路由添加children属性:[
{
path:""二级路由是没有`/`,
name:
component:
}
]
3、找地方显示路由组件
给谁配置的二级路由就去当前组件中找位置
4、设置导航路径
记录 设置to="/一级路由/二级路由"
5、设置二级的默认路径
配置二级路由参考代码(我这里写的是json之前写后台管理自己乱写的数据)
"router": [
{
"path": "/index",
"name": "index",
"component": "index",
"children":[
{
"path":"a",
"name": "a",
"component": "a"
},
{
"path":"b",
"name":"b",
"component": "b",
"children":[
{
"path":"b1",
"name": "b1",
"component": "b1",
"children":[
{
"path":"bb1",
"name": "bb1",
"component": "bb1"
}
]
}
]
}
]
},
{
"path": "*",
"name": "404",
"component":"404"
}
]
const routes = [
{
path:"/",
redirect:"/login"
},
{
path: '/login',
name: 'login',
component: () => import('../views/login.vue')
}
]
在配置路由的时候会发现有两种引入方式一种是直接import引入import home from "@/views/home"
另一种是使用箭头函数引入() => import('../views/login.vue')
下面说一下他们的区别,以及用哪个比较好
1、直接把组件引入进来,不管路径访问或不访问,都会把组件引用进来
2、是当我访问这个路径的时候才加载这个路径,如果一直不访问/logint
这个路径是不会加载的。
好处就是当项目比较大,页面比较多,因为vue是单页面应用,一次性加载这么多内容,加载会很慢,这样体验就很不好。
所以在真正的项目中,一般使用第二种异步加载/懒加载,就是访问了才加载,没有访问就不加载。
路由传参
为什么会用到路由传参:
由多个路由导航调转到同一个路由页面,又得区分是从哪个导航跳转过来的,那么就需要路由传参
query传值
传值格式路径?参数名=值&参数名=值
步骤:
1、在router-link的to属性后面 设置参数to="/path?参数名=值"
2、获取 在目标组件上获取this.$route.query.id
来获取到参数
params传值
传值格式 路径/值/值/值
步骤:
1、在router->index.js
中设置参数
{
path:"/path/:参数名/:参数名"
}
2、在router-link的to属性后面 设置值to="/path/值/值"
3、在在目标组件上获取this.$rotue.params.参数名
路由跳转的几种方式
router-link
1. 不带参数
<router-link :to="{name:'home'}">
<router-link :to="{path:'/home'}"> //name,path都行, 建议用name
// 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。
2.带参数
<router-link :to="{name:'home', params: {id:1}}">
// params传参数 (类似post)
// 路由配置 path: "/home/:id" 或者 path: "/home:id"
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
<router-link :to="{name:'home', query: {id:1}}">
// query传参数 (类似get,url后面会显示参数)
// 路由可不配置
// html 取参 $route.query.id
// script 取参 this.$route.query.id
this.$router.push() (函数里面调用)
1. 不带参数
this.$router.push('/home')
this.$router.push({
name:'home'})
this.$router.push({
path:'/home'})
2. query传参
this.$router.push({
name:'home',query: {
id:'1'}})
this.$router.push({
path:'/home',query: {
id:'1'}})
// html 取参 $route.query.id
// script 取参 this.$route.query.id
3. params传参
this.$router.push({
name:'home',params: {
id:'1'}}) // 只能用 name
// 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
4. query和params区别
query类似 get, 跳转之后页面 url后面会拼接参数,类似?id=1, 非重要性的可以这样传, 密码之类还是用params刷新页面id还在
params类似 post, 跳转之后页面 url后面不会拼接参数 , 但是刷新页面id 会消失
this.$router.replace() (用法同上,push)
this.$router.go(n)
向前或者向后跳转n个页面,n
可为正整数或负整数
区别:
this.$router.push
跳转到指定url路径,并想history
栈中添加一个记录,点击后退会返回到上一个页面
this.$router.replace
跳转到指定url路径,但是history
栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面)
this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数
axios
Axios是什么?
Axios 是一个基于 promise
的 HTTP 库,简单的讲就是可以发送get、post请求。说到get、post,大家应该第一时间想到的就是Jquery吧,毕竟前几年Jquery比较火的时候,大家都在用他。但是由于Vue、React等框架的出现,Jquery也不是那么吃香了。也正是Vue、React等框架的出现,促使了Axios轻量级库的出现,因为Vue等,不需要操作Dom,所以不需要引入Jquery.js了。
Axios特性
1、可以在浏览器中发送 XMLHttpRequests
2、可以在 node.js 发送 http 请求
3、支持 Promise API
4、拦截请求和响应
5、转换请求数据和响应数据
6、能够取消请求
7、自动转换 JSON 数据
8、客户端支持保护安全免受 XSRF 攻击
Axios用在什么场景?
浏览器发送请求,或者Node.js发送请求都可以用到Axios。像Vue、React、Node等项目就可以使用Axios,如果你的项目里面用了Jquery,此时就不需要多此一举了,jquery里面本身就可以发送请求。
Axios如何使用?
安装模块
npm install axios --save
在vue文件中引入 import axios from axios
写在export default
上面
或者直接引入
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
引入模块后可以直接使用
// GET
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// POST
axios.post('/user', {
name: 'Javan',
website: 'www.javanx.cn'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 参数时可选的
如果想并发多个请求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求都执行完成才会执行
}));
main.js中axios的全局设置
axios的全局设置
import axios from 'axios'
Vue.prototype.$axios=axios
在组件中可以直接通过 this.$axios
来使用
这里就不写这么多了,下面来封装 axios
封装axios请求
基本不用封装,因为Axios
本身是一个基于 promise
的 HTTP
库只是对请求的接口
地址,超时
,报错
处理
首先在src目录中创建一个http文件夹,在http目录下新建request.js
api.js
在request.js
中
import Axios from 'axios'
// Axios.defaults.withCredentials = true
// console.log('request.js中的环境变量:', process.env.BUILD_ENV)
// 针对npm run 来自动读取不同环境变量
// const config_env = require(`../build/${
process.env.BUILD_ENV}.js`)
// eslint-disable-next-line
const config_env = require(`../build/${
process.env.BUILD_ENV}.js`)
// 创建axios实例
const service = Axios.create({
baseURL: 'https://www.liulongbin.top:8888/api/private/v1',
timeout: 3000
})
// 请求拦截
service.interceptors.request.use(config => {
// console.log('请求被拦截:', config)
const token = localStorage.getItem('token')
// 配置头信息
if (token) {
config.headers.Authorization = token
}
return config
}, _error => {
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject('请求出错,请检查')
})
// 响应拦截
service.interceptors.response.use(res => {
// console.log('响应拦截')
return res
}, error => {
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject('出错啦', error)
})
export default service
这里只需要简单配置一下请求拦截,相应拦截 header头token 在请求拦截相应拦截里面配置对应的相应,比如token过期,服务器异常等等
在api.js
中
import request from './request'
import qs from 'qs'
export function login (obj) {
return request({
url: 'login',
method: 'post',
data: qs.stringify(obj)
})
}
/**
* 用户列表接口
*/
export function getUser (params) {
return request({
url: 'users',
method: 'get',
params
})
}
首先引入request,qs呢是一个转换用的,给后台发送数据时需要
使用:
那个文件请求在哪个文件中引入
import {
login } from '@/http/api'
直接异步请求
login(this.ruleForm).then((res) => {
// console.log(res)
// 搞到token
const token = res.data.data.token
// console.log(token)
// 存放到本地
localStorage.setItem('token', token)
// 登录ok咱就跳转到首页 /
this.$router.push('/index')
})
} else {
this.$message.error('登录失败')
return false
}
})
跨域
由于浏览器的同源策略,我们只能通过ajax访问同域名 同协议 同端口号的数据,如果域名不同、协议不同、端口号不同、ip地址和域名之间的访问都属于跨域。跨域的其中一种解决方案是jsonp,因为script img的src属性没有被同源策略限制,所以我们可以通过script标签src属性来实现调用不同域名 不同协议 不同端口号的数据。jsonp的原理是利用动态的创建script标签来请求后端接口的地址,然后传递一个callback参数,后端接受到callback后将数据处理完成,将数据以callback函数调用的方式来返回,callback的参数就是我们要的json数据
我这里简单明了说一下,以及在本地写好后,打包上传需要注意的事情
首先在vue.config.js
中写入
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://40.00.100.100:3002',//对应自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
//这里理解成用‘/api’代替target里面的地址
//后面组件中我们掉接口时直接用api代替
}
}
}
}
}
比如我要调用http://40.00.100.100:3002/user/add
,直接写/api/user/add
即可
注:这只是在本地我们看效果,如果要发布到线上,把配置的跨域删掉就行了,打包发布过后域名啥的都一样了不存在跨域了,还需要注意的是之前接口前面写的/api
如果后台配置了那就配置了,不用管它,如果没有配置那么请求的时候域名就会变成http://40.00.100.100:3002/api/user/add
多了api肯定是不对的,那么把/api
删掉即可 (在baseURL中配置会更方便的更改)
keep-alive
keep-alive是vue提供给我们的一个组件 来缓存我们页面的数据
全部缓存
直接把 router-view
用 keep-alive
包裹起来
部分缓存
1、router.js
中设置要缓存的页面
{
path: '/child1',
name: 'Child1',
component: Child1,
meta:{
keepAlive:true
}
},
{
path: '/child2',
name: 'Child2',
component: Child2,
meta:{
keepAlive:false
}
}
2、用 v-if 来显示 router-view
是否在 keep-alive
中出现
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
有些页面数据需要缓存,但是数据更新时怎么办,结合keep-alive
的生命周期去做逻辑处理
activated
activated
页面第一次进入的时候,钩子触发的顺序是created->mounted->activated
deactivated
deactivated
页面退出的时候会触发deactivated
,当再次前进或者后退的时候只触发activated
路由导航守卫
作用:
当从一个路由页面到另一个路由页面,如果有权限,能进入,没权限,阻止进入
类别:
全局守卫
路由独享守卫
组件内部守卫
其实就是利用路由跳转之前的那一刹那我们让他们帮我干一些事情
路由导航守卫就是利用路由导航钩子来添加自己代码,实现我们想要的功能
路由守卫是由路由钩子完成
全局守卫
只要涉及到路由跳转 这个钩子就会执行
配置:router->index.js中去配置
router.beforeEach((to, from, next) => {
console.log(to) => // 到哪个页面去?
console.log(from) => // 从哪个页面来?
next() => // 一个回调函数
})
// to和from都是一个对象
// next是一个回调函数 next()==next(true) 放行 next(false)阻止
注意:
to 对象 去哪个路由的对象
from 从哪来的对象
next() 是否继续回调函数
如果不写 --- next(false)
next() --- next(true)
next(path) 相当于调转
路由独享守卫
路由独享守卫是在路由配置页面单独给路由配置的一个守卫
{
path: '/',
name: 'home',
component: 'Home',
beforeEnter: (to, from, next) => {
// ...*************
}
}
组件独享守卫
组件路由守卫是写在每个单独的vue文件里面的路由守卫
beforeRouteEnter (to, from, next) {
// 注意,在路由进入之前,组件实例还未渲染,所以无法获取this实例,只能通过vm来访问组件实例
next(vm => {
})
}
beforeRouteUpdate (to, from, next) {
//当路由参数发生改变的时候被调用
}
beforeRouteLeave (to, from, next) {
// 离开当前路由页面时调用
}
vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
vuex的工作流程
在vue的组件中通过dispatch
来调用actions
中的方法,在actions
中通过commit
来调用mutations
中的方法,在mutations
中可以直接操作state
中的数据,只要state
中的数据发生改变就会立刻响应
到咱们的组件中
之前使用vuex还得需要npm install vuex --save
下载,现在安装脚手架的时候直接可以选择下载了
state
:是仓库 也就是存储数据的 相当于银行的金库
组件使用state中的数据
this.$store.state.属性
mutations
:是唯一可以修改vuex
中数据的选项 ,每个方法都有一个回调函数 回调函数有一个形参state
就是咱们的state
数据
在组件中触发mutations中的方法
this.$store.commit("方法名",参数)
action
:不能直接修改状态值 调用mutation
的方法 mutation
修改状态值 可以包含异步操作
在组件中触发action中的方法
this.$store.dispatch("方法名",参数)
getters
:类似于我们的计算属性 可以对state中的数据做一些逻辑计算
在组件中使用:
this.$store.getters.方法名
vuex module
vuex的工作流程:
state
:存储数据的仓库
mutations
:定义的是操作state数据的方法
getter
:定义的state数据一些逻辑处理 相当于我们的computed
actions
:实现的是异步操作数据 通过commit调用mutations中的方法
module
:将vuex中的数据分块来存储 模块中state是局部的,getters mutations actions都是全局的直接使用就是 只有局部的是要加模块名 $store.state.模块名.属性名
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter
调用模块中state中的数据
$store.state.模块名.属性名
调用模块中getter中的方法
$store.getter.名
调用模块中的mutations
$store.commit("名",参数)
调用模块中actions
$store.dispath("名",参数)
注意的是:
模块中state是局部的,getters mutations actions 都是全局的直接使用就是 只有局部的是要加模块名
vant、elementUI、ECharts
这里不多介绍了,我们都知道vue呢他是一个渐进式的框架,轻量级,可以在项目中可以使用其他的框架或者类库。
vant (移动端使用)
上手也是比较简单的直接去官网看快速上手
快速上手
首先安装 npm i vant -S
在main.js引入
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);
找到代码复制
如果你想更改颜色样式什么的,下面有对应的api以及事件,自行去看
elementUI (pc端使用)
elementUI就和vant这种一样了,会一个别的也就差不多了,直接上链接
快速上手
ECharts
ECharts呢也是一样的
快速上手
这里简单介绍一下
首先 npm install echarts --save
下载安装
使用:
首先在组件中准备一个具备高宽的 DOM 容器,用来展示echarts
引入:
import * as echarts from 'echarts';
找到示例,随便找出一张
复制的是一个option
对象,那么如何写入呢,分为三步
首先获取容器
var myChart = echarts.init(document.getElementById('main'));
第二部写入option对象
最后使用刚指定的配置项和数据显示图表
myChart.setOption(option);
最终效果:
总结
本文简单介绍了vue的使用,如有遗漏,留言后补~