选项:el data methods watch computed 生命周期 components filters
---------------------------------------------------------------------
new Vue({
el : '#app',
data() {
return {
}
},
created () {
},
methods: {
}
})
----------------------------------------------------
创建 vue create 项目名称
Manually select features —— 自定义配置 *
Babel —— ES6 向下兼容 ES5 *
Router —— 路由 *
Vuex —— 用于管理数据 *
In package.json *
Save this as a preset for future projects? (y/N) —— 是否存为默认预设
进入 cd 项目名称
启动npm run serve
安装axios,文件根目录下安装,指令如下: npm i axios -s
安装Element,文件根目录下安装,指令如下:npm i element-ui -s
安装Vant,文件根目录下安装,指令如下:
按照路由spa,npm i vue-router@^3.5.1 -s //Vue2·npm i vue-router -s //Vue3
创建 router文件夹 并创建 index.js
----------------------------------------------------------
axios使用方式:
---main.js
import axios from 'axios'
Vue.prototype.$axios = axios
-------------------------------------------------------------
Element使用方式:
在main.js文件中引用:
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(Element);
添加再
import Vue from 'vue'
import App from './App.vue'
下一行中
每次需要通过cd 进入到 项目根目录
------------------------------------------------------------------
npm run serve 启动项目 -- serve是可以修改的 在package.json配置查找
每次项目都需要改命令启动,给有一个http地址,访问该地址就可以访问项目
npm run build 项目打包命令 -- 项目开发完成以后执行的命令
会压缩项目使用的所有文件和你自己写的源码并进行编译 得到dist目录
--------------------------------------------------------------
目录结构:
node_modules: 脚手架的源码、npm安装的所有依赖
该目录可以删除 (npm i)就可以完全重新安装了
public : index.html 特殊第三方文件 这个目录会直接打包进行 不会编译
src : 开发的工作目录
assets: 静态资源 图片、css
components : 一般组件
views: 路由组件
https: 接口
utils: 公共模块库
...
App.vue: 根组件
main.js: 入口文件
组件:.vue文件
每个组件有3个组成部分:、
1、template : 模板、视图 -- 负责html结构 配合指令 构建出结构
只能有一个根标签
2、script: 负责业务逻辑 这里的 {} 就是你平时new Vue包的那个{}
支持之前讲的所以选项如data/methods/computed/watch
export default { ... }
3、style: 负责样式
<style scoped></style>
scoped : 当前组件(.vue)申明样式,只对当前组件有效
----------------------------------------------------
***.split('').reverse().join('')--反转***的内容
先转为数组,再反正数组顺序,再转为字符串
----------------------------------------------------
data:
内部使用:this.属性名 this.属性名 = 值 this.$data获取所有
外部使用:vm.属性名 vm.$data
--------------------------------------------------------------
methods:
内部:this.方法名()
外部:vm.方法名
-------------------------------------------------------------
{{}}插值表达式, 用于输出对象属性和函数返回值。
v-text将数据填充到标签
v-html输出 html 代码
v-show用来决定某一个元素是否在页面中显示出来
v-bind-- ‘:’ 用于绑定数据和元素属性
v-on--‘@’ 用于绑定事件监听器
ref 获取DOM,操作DOM
$refs 通过$refs属性拿到ref这个dom元素
v-model在表单 、 及 元素上创建双向数据绑定
---------------------------------------------
插值表达式和v-text:会把里面的实体标签<> 转义为符号(< >) 失去标签意义;
---安全考虑,防止xss攻击行为
--------------------------------------------------
条件渲染:
根据条件来控制指令对应的标签是否渲染出来
v-if:根据表达式的值的真假条件渲染元素
v-else-if:前一兄弟元素必须有 v-if 或 v-else-if
v-else:前一兄弟元素必须有 v-if 或 v-else-if
v-show:根据表达式之真假值,切换元素的 display css属性
如果需要频繁改变显示状态,建议使用v-show;
-------------------------------------------
v-for:
<h2>数字的循环渲染</h2>
<div v-for="item,index in number">{{index}} -- {{item}}</div>
<div>-------------</div>
<h2>字符串的循环渲染</h2>
<div v-for="item,index in message">{{index}} -- {{item}}</div>
<div>-------------</div>
<h2>数组的循环渲染</h2>
<div v-for="item,index in list">{{index}} -- {{item}}</div>
<div>-------------</div>
<h2>对象的循环渲染</h2>
<div v-for="item,key,index in zs">{{index}} -- {{key}} -- {{item}}</div>
<div v-for="item in zs">{{item}}</div>
-------------------------------------------------------------
属性绑定:
> v-bind:属性名="表达式" < ===== > :属性名="表达式" <
标签的属性对应的值,这个值会使用变量
---------------------------------------
事件绑定:
> v-on:事件名.事件修饰="表达式" < ==== > @事件名.事件修饰="表达式" <
去掉on
<a href="https://www.baidu.com">点击以后默认行为是跳转</a>
<a href="https://www.baidu.com" @click="myclick4">阻止默认行为,
自行解决:event.preventDefault()</a>
<a href="https://www.baidu.com" @click.prevent="test">阻止默认行为,加.prevent修饰</a>
---------------------------------------------------
vue 获取dom对象
第一步:
<input type="text" placeholder="请输入用户名" ref="username">
给需要获取DOM对象元素加一个ref属性 ref的值随便填写一个你自定义的标识符
第二步:
this.$refs 就可以获取到所有带有ref属性的 DOM对象对象集合;
该对象的格式就是一元素的ref属性值 指向 对应的DOM对象
----------------------------------------------------------------
v-model在表单 、 及 元素上创建双向数据绑定
单行文本框和密码输入框 双向绑定原理:
<input type="text" placeholder="请输入用户名" v-model="username"> <br>
<input type="text" placeholder="请输入用户名" :value="username"
@input="username = $event.target.value"> <br>
下来以后把多选、下拉等表单元素的双向绑定原理掌握 !
v-model.trim : 去除掉收尾空格
v-model.number : 将值自动转换为数字
v-model.lazy : 将输入框的监听的input事件改为change
----------------------------------------------------------
监听器 watch
方式一:直接定义一个方法 方法名就是你需要监听的变量名 可以获取到修改之后和之前的值
// count(newVal, oldVal) {
// console.log(66, 'count变量改变了', this.count);
// this.countPf = this.count ** 2;
// }
方式二:对象 该对象下必须有handler来定义回调动作 和方式一等效
count:{
handler(newVal, oldVal) {
console.log(66, 'count变量改变了', this.count);
this.countPf = this.count ** 2;
}
}
count:{
handler(newVal, oldVal) {
console.log(66, 'count变量改变了', newVal, oldVal);
this.countPf = this.count ** 2;
},
immediate: true // 默认false 需要真正发生了改变才执行 true: 会先执行一次
}
每个监听可以有3个属性:
handler:回调函数 必须 如果直接定义的方法 默认就是定义了handler
immediate:默认false, 需要真正发生了改变才执行; true 会先执行一次
deep: 默认false浅监听,只能监听变量本身的改变;
true 深度监听 里面的某个属性发生改变也可以监听到
---------------------------------------------------------------------
计算属性 computed
它的本意和data中一样,都是当前的全局变量,
使用语法都是一致 this.变量名 {{变量名}};
但是它的值,没法直接确定,而需要计算(函数处理)得来(返回值决定)。
计算属性中变量和 data中变量,不能重名。
和普通方法相比,它自带缓存功能
里面使用过变量,发生了改变,就会重新执行;它也是响应式
方式一:直接是方法,表示只定义get回调;之后获取该变量得值,而不会对该变量赋值
countLf() {
console.log('countLf执行了', Math.random());
return this.count ** 3
},
方式二:对象,对象中需要定义get和set回调
当需要获取变量值的时候,get回调会自动执行,该回调返回值就是变量的值
当需要修改变量值的时候,set回调会自动执行
countLf: { // 和方式一等效
get() {
console.log('countLf执行了', Math.random());
return this.count ** 3
}
}
---------------------------------------------------------------------
生命周期
beforeCreate 创建前 还没有加载data和methods选项 因此不能通过this.变量获取数据
created 创建完成 data methods都已经加载 因此可以获取变量或调用方法 *****
beforeMount 渲染之前
mounted 初次渲染之后 这里以后才可以第一时间获取DOM对象 *****
beforeUpdate
updated
beforeDestroy
destroyed
-----------------------------------------------------------------------
组件:
App.vue父组件引用子组件:
父组件:
import 子组件名 from "@/components/子组件.vue"
export default{
components:{
子组件名:子组件
},
}
子组件在父组件使用:
<子组件名></子组件名>
<子组件名>
--------------------------------------------------
全局组件注册:一旦注册,每个组件都可以使用的组件标签
main.js:
import Sun from './components/Sun.vue'
Vue.component('Sun', Sun)
-------------------------------------------------------
动态组件: 具体加载的那个组件是可变,可以使用变量来控制,而且是响应式
import Child from './components/Child.vue'
import Sun from './components/Sun.vue'
渲染动态组件:component组件是vue内置组件,
必须有一个is的属性 来指定真正的组件名
<component :is="mycom"></component>
mycom = 'Child' //mycom是变量可变为Sun等
----------------------------------------------------------
模块化:主要用于封装一些方法,然后进行引入,简化代码,提高代码复用率
模块:《一个js文件》,理解为一个模块;默认情况这个文件有自己独立的作用域,
该文件中定义变量或函数,外面也不能直接获取到。
哪些变量或函数,你希望外面可以获取,需要通过export 或 export default 暴露出去。
export let * =值 分别暴露*
export{*,*} 统一暴露*
export default * 默认暴露*
-引入
import * from 'js文件地址'
使用
created(){
console.log(*)
}
css文件引入:
script中引入:
import "./assets/css/common.css"
require('@/assets/css/common.css')
style中也可以引入:
<style scoped>
@import url('./assets/css/common.css');
</style>
图片的引入:
<div>
<img src="./assets/logo.png"/>
</div>
<div>
<img src="@/assets/logo.png"/>
</div>
<div>
<img src="http://demo2.wooadmin.cn/uploads/thumb/132628ceed4b35884337f7be0a356c19.jpg"/>
</div>
<div>
<img :src="src"/> // src : require('./assets/logo.png'),
如果是本地图片需要先使用require加载
</div>
<div>
<img :src="src2"/>
</div>
----------------------------------------------------------
过滤器
有的数据,真实存储值和实际希望展示值有区别的,
这个时候就可以考虑使用考虑器在渲染展示的时候把真实值处理为我们需要展示的方式
定义局部过滤器:只能当前组件使用的过滤器
1、定义在当前组件的filters选项中
filters: {
ucfirst(value) {
return value[0].toUpperCase() + value.substr(1).toLowerCase();
},
showMoney(value, point = 2) {
return "¥" + value.toFixed(point);
},
},
2、调用过滤器
<div>word:{{ word | ucfirst }}</div>
<div>money:{{ money | showMoney }}</div>
<div>price:{{ price | showMoney(3) }}</div>
把当前使用过滤器的变量的值传入过滤器方法的第一个参数;
如果过滤器本身也有参数从二个开始传入
---------------------------------------------------------
prop:用于父组件向子组件进行单向通信
子组件:
expoet defaulr{
props:{
prop名:String,
prop名:Number,
},
}
父组件:
<div :prop名:值 :prop名:值></div>
每个prop支持的属性:
type: 定义传递的数据的数据类型
required: 表示该prop是必传的 默认 false
default: 针对非必传的prop的默认值
validator:自定义prop的验证规则
支持的类型:
String
Number
Boolean
Array
Object
Date
Function
Symbol
{{$props}} 以对象的形式获取到所有的prop值
-----------------------------------
$emit 子组件传值到父组件
子组件:"$emit('emit名',值)"
父组件:$event=值
子组件:
$emit(emit名,值)
1.<div @click事件="$emit('emit名',值)"></div>
2.<button @click="login">登录</button>
methods:{
login() {
this.$emit('login', this.username) // 触发当前组件的自定事件
},
}
父组件:
1.<div @emit名="$event"></div>
2.<div v-else>
<login @login="mylogin"></login>
</div>
methods: {
mylogin($event) {
this.logined = $event;
}
},
针对真正原生事件可以给原生事件加.native的修饰;
才会把该事件解析为原生事件,而不需要子组件通过$emit触发了
<MyEmit @click.native="myclick"></MyEmit>
$parent、$children、$refs
在子组件中可以通过 this.$parent 直接获取到父组件实例
在父组件中可以通过 this.$children 以数组的形式获取到所有子组件的实例 不推荐 vue3废弃
推荐使用 ref
可以给组件标签加ref属性 通过this.$refs.xxx 获取到指定子组件的实例 ****
--------------------------------------------------------------
插槽
父组件调用某个子组件的时候,可以由父组件自行定义部分 子组件中需要使用的 html结构
如果是prop解决是数据差异问题,那么插槽解决就是结构的差异问题
匿名插槽 -- 一个组件一般只放一个匿名插槽 (没有name属性的slot,其实默认name叫default)
子组件:
<slot>默认的html结构</slot>
父组件:
需要先引用子组件
<子组件名>
<div>
<h2>
{{logo_title}}<span style="color: red">*</span>
</h2>
</div>//把该结构渲染的结果 替换 到子组件的 slot位置去
</子组件名>
具有插槽 -- 一个组件可以定义多个具名插槽, 给每个slot预留位置通过name属性取一个名字
子组件:
<slot name="**">默认的html结构</slot>
父组件:
需要先引用子组件
<子组件名>
<template v-slot:**>不写v-slot 默认 v-slot:default 给匿名插槽|v-slot: 可以简写成 #
<div>
<h2>
{{logo_title}}<span style="color: red">*</span>
</h2>
</div>//把该结构渲染的结果 替换 到子组件的 slot位置去
</template>
</子组件名>
作用域插槽 ****
子组件在通过slot组件(<slot name="after"></slot>)准备插槽位置的时候,
可以在该slot标签上以自定义属性的形式提供一些属性数据;
然后父组件再指定对应插槽内容的时候 可以获取到子组件的slot标签上所提供的数据。
5-1、子组件通过自定义属性的形式 在slot上提供数据
<slot name="after" :index="index" :nav="nav"></slot>
------------------------------------------------------------
provide + inject 提供与注入 适用于父辈祖先组件传值给后代组件 ****
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,
不论组件层次有多深,并在其上下游关系成立的时间里始终生效
父辈组件:
provide(){
return{
*:"值",
**:"值",
};
},
后代组件:
方式一:
inject:['msg', 'b']
注入以后就按当前组件变量来使用了
{{msg}} {{b}}
this.msg this.b
方式二:
inject:{
yemsg: {
from : 'msg'
},
b: {
from :'b'
},
d: {//没有被父辈组件提供的数据可定义默认值
from :'d',
default : 5 // 默认值 和props默认值一样 基本类型直接写 复杂类型应该是函数返回
}
},
提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。
然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
App.vue是根组件,它是所有其他组件的祖先,
如果是App.vue中provide的数据,那么在其他组件中都是可以获取的。
-----------------------------------------------
组件之间的双向绑定 v-model
my-input :value="username" @input="username = $event"></my-input> 可以简写成:
<my-input v-model="username"></my-input>
获取值的prop名必须是value,通过值改变的自定义事件(event)名必须是input ,
才可以缩写成v-model
如果prop名和事件名 确实希望改变,可以在子组件通过 model选项来指定它们的名称
model : {
prop : 'value' // 指定双向绑定prop名
event: 'click' // 默认事件名 input
}
父组件:
<my-input :val="username" @test="username = $event"></my-input> 可以简写成:
<my-input v-model="username"></my-input>
子组件:
model:{
prop : 'val',
event: 'test'
}
------------------------------------------------------------------------------------
路由:
单页Web应用(single page web application,SPA),就是只有一张Web页面的应用。
单页应用程序 (SPA) 是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。?
浏览器一开始会加载必需的HTML、CSS和JavaScript,
所有的操作都在这张页面上完成,都由JavaScript来控制。
url:
协议://域名或ip:端口/目录/文件名?参数1=值1&参数2=值2
http 默认端口 80
https 默认端口 443
达到目的和传统网站(多页面网站,每个页面都有一个对应的url地址)类似,
通过不同的url地址来实现组件的自动切换。
/ Home.vue
/about About.vue
/goods Goods.vue
/news News.vue
手动集成路由流程:
a、安装vue-router
npm i -S vue-router@3
b、目录结构调整
router/index.js 放置路由配置 定义url和路由组件的映射关系
components : 用于存放一般组件
views :用于存放路由组件
一般组件和路由组件:
一般组件:需要导入、注册、组件标签,手动加载;不需要做配置;具体的布局点、功能
路由组件:根据url改变自动切换;需要做路由配置;理解为传统网站中"页面"
c、配置 router/index.js:
import Vue from 'vue'
import VueRouter from 'vue-router'
1、如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)
Vue.use(VueRouter)
2、定义 (路由) 组件
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import News from '../views/News.vue'
import Goods from '../views/Goods.vue'
import NotFound from '../views/NotFound.vue'
3、配置每个路由组件 和 url的 一一对应映射关系 这里就是以后路由的主要工作点
const routes = [
{
pqth:'/',
redirect:'/routes'--重定向
}
{
path: '/routes', // 访问的url
component : Home,// 希望自动加载的组件
name : 'Home' // 当前配置的标识 后续通过该标识定位到当前的配置
},
{
path: '/about',
component : About,
name : 'About'
},
{
path: '/news',
component : News,
name : 'News'
},
{
path: '/goods',
component : Goods,
name : 'Goods'
},
{
path: '*',
component : NotFound,
name : 'NotFound'
}
];
路由配置:
定义每个路径组件和url的一一对应映射关系;每个配置都是一个对象
每个配置都应该有的三个基本属性:path、component、name
·path: 定义url地址
·component: 路由组件
·name:当前配置一种标识,可以通过该标识来反向查找到当前路由配置
·redirect : 重定向 当配置当前path以后 自动将url切换到 指定的另外一个path去
组件的两种加载方式:
方式一:上面那种先定义再配置
import Home from '../views/Home.vue'
component: Home
方式二:懒加载 真正需要渲染当前路由组件的时候才加载 从优化角度 效果高
component: () => import('../views/About.vue')
》把常用、首页用方式一加载;其他使用方式二《
404路由配置:
{
path: '/404',
name: 'NotFound',
component: () => import('../views/NotFound.vue')
},
{
path: '*',
name: 'NotFound',
redirect: '/404'
}
4、实例化路由
const router = new VueRouter({
routes
});
5、把路由实例暴露出去
export default router;
d、mian.js
导入VueRouter实例
import router from './router'
new Vue({
render: h => h(App),
router 把VueRouter实例 放入到 router选项中
后期就可以通过 this.$router 来获取到该实例
}).$mount('#app')
e、App.vue 根组件 预留路由出口
<router-view></router-view>所有路由组件根据url切换自动渲染,
底层会把路由组件渲染的结果自动替换到该路由出口的位置。
路由跳转:
从一个路由组件跳转到另外一个路由组件
方式一:标签 router-link --- 相当于传统 a标签
<router-link to="/category">必须包含to属性来指定需要跳转的路由</router-link><br/>
<router-link to="/category" tag="h2">可以通过tag属性来改变生成的标签名,默认是a标签,v4已移除</router-link><br/>
<router-link to="/" exact>精准匹配 包含的时候就不会加上 router-link-active;另外一个解决方案 首页不要是/path 但需给/做重定向</router-link><br/>
<router-link to="/category" active-class="my-active">可以使用active-class自定义部分匹配上以后类名</router-link><br/>
<router-link to="/category" exact-active-class="my-exact" active-class="my-active">可以使用exact-active-class自定义精确匹配上以后类名</router-link><br/>
<router-link :to="{path: '/category'}">除了字符串以外,也可以使用对象来标识新路由</router-link><br/>
<router-link :to="{name: 'Category'}">也可以通过name来标识对应路由</router-link><br/>
<router-link to="/category?type=5&limit=10">以get参数的格式传递传输;url上可见;有$route.query获取</router-link><br/>
<router-link :to="{path: '/category', query:{type: 6, limit: 20}}">已对象的形式传递get参数 和 上面等效;由$route.query获取</router-link><br/>
<router-link :to="{name: 'Category', query:{type: 7, limit: 30}}">和上面等效</router-link><br/>
<router-link :to="{name: 'Category', params:{x: 'xx', y: 'yy'}}">另外一种传参方式,只能使用name标识,不能path标识,类似于post参数,已隐藏方式传递,由$route.params</router-link><br/>
<router-link :to="{name: 'Category', query:{type: 8, limit: 40}, params:{x: 'xx', y: 'yy'}}">query和params参数一起</router-link><br/>
<router-link to="/category" replace>默认等效于push,会增加历史记录;加上replace属性以后就等效于router.replace方法</router-link>
方式二:编程式导航 通过js一种跳转方式 --- 相当于传统 location.href = '新地址'
可以通过 this.$router来实现跳转
<router-link to="/category">必须包含to属性来指定需要跳转的路由</router-link><br/>
this.$router.push('/category')
<router-link :to="{path: '/category'}">除了字符串以外,也可以使用对象来标识新路由</router-link>
this.$router.push({path: '/category'})
<router-link :to="{name: 'Category'}">也可以通过name来标识对应路由</router-link>
this.$router.push({name: 'Category'})
<router-link to="/category?type=5&limit=10">以get参数的格式传递传输;url上可见;有$route.query获取</router-link>
this.$router.push('/category?type=5&limit=10')
<router-link :to="{path: '/category', query:{type: 6, limit: 20}}">已对象的形式传递get参数 和 上面等效;由$route.query获取</router-link>
this.$router.push({path: '/category', query:{type: 6, limit: 20}})
<router-link :to="{name: 'Category', query:{type: 7, limit: 30}}">和上面等效</router-link>
this.$router.push({name: 'Category', query:{type: 7, limit: 30}})
<router-link :to="{name: 'Category', params:{x: 'xx', y: 'yy'}}">另外一种传参方式,只能使用name标识,不能path标识,类似于post参数,已隐藏方式传递,由$route.params</router-link>
this.$router.push({name: 'Category', params:{x: 'xx', y: 'yy'}})
<router-link :to="{name: 'Category', query:{type: 8, limit: 40}, params:{x: 'xx', y: 'yy'}}">query和params参数一起</router-link>
this.$router.push({name: 'Category', query:{type: 8, limit: 40}, params:{x: 'xx', y: 'yy'}})
this.$router.replace(...) 用法和push一致 实现跳转 push新增历史记录 才可以返回
this.$router.back()
this.$router.forward()
this.$router.go(-1)
路由传参:
会多这2个全局变量
this.$router: 路由器 VueRouter实例 一般用于路由跳转
this.$route: 获取当前正在访问的路由相关信息 比如获取路由参数等
方式一:query 类似于get请求 会把参数放url上 可见的 推荐 由this.$route.query获取
this.$router.push({path: '/category', query:{type: 6, limit: 20}})
this.$router.push('/category?type=5&limit=10')
方式二:params 类似于post请求 以隐藏方式传递 只能使用name标识 由 this.$route.params获取
this.$router.push({name: 'Category', params:{x: 'xx', y: 'yy'}})
方式三:props 理解为底层调用路由组件的时候 往该组件标签上传递了标签属性
1、静态对象 this.$attrs 或 this.$props 获取
{
path: '/category',
name: 'Category',
component: () => import('../views/Category.vue'),
props:{x: 'xxx', y: 'yyy'}
}
理解为 底层在<router-view/>中 也像这样(组件标签)调用了 路由组件 只是我们没有亲自写而已:
<category v-bind="{x: 'xxx', y: 'yyy'}"></category>
<category x="xxx" y="yyy"></category>
2、布尔 true 自动将params参数转换为props
props:true
<category v-bind="$route.params"></category>
3、函数 将函数处理以后的返回值对象 转换为props
props: () => {
return {
x : 'myxx6',
y:'myyy6',
z : 'myzz6'
}
}
4、函数 接收一个参数 就是当前的this.$route
props: (route) => Object.assign({}, route.query, route.params) 将query 和 params都转换为props
方式四:动态路由 由 this.$route.params 获取
{
path: '/list/:cid',
name: 'List',
component: () => import('../views/List.vue')
},
:to="'/list/' + item.id"
-----------------------
多级路由:
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
redirect : '/about/gsjs', // 当访问一级路由的时候 自动跳转到第一个子路由
children:[
{
path: 'gsjs',
name: 'Gsjs',
component: () => import('../views/Gsjs.vue')
},
{
path: 'ldzc',// 没有 / 打开 path 在父路由的path基础 追加 /自己的 /about/ldzc
name: 'Ldzc',
component: () => import('../views/Ldzc.vue')
},
{
path: 'tdfc',
name: 'Tdfc',
component: () => import('../views/Tdfc.vue')
}
]
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
children:[
{
path: '', // /about 访问的时候 实际渲染的路由是 Gsjs
name: 'Gsjs',
component: () => import('../views/Gsjs.vue')
},
{
path: 'ldzc',// 没有 / 打开 path 在父路由的path基础 追加 /自己的 /about/ldzc
name: 'Ldzc',
component: () => import('../views/Ldzc.vue')
},
{
path: 'tdfc',
name: 'Tdfc',
component: () => import('../views/Tdfc.vue')
}
]
},
注意:
谁有子路由(children),对应组件上一定加 路由出口 <router-view></router-view>
一级路由的出口在App.vue 根组件中
-----------------------
路由缓存 keep-alive:
1、把路由出口使用 keep-alive 包裹住;切换路由的时候,路由组件就会自动缓存,切换回来就无需重新创建
<keep-alive>
<router-view></router-view>
</keep-alive>
2、使用include来指定需要的组件才缓存,其他的不缓存
<keep-alive include="Home,Category">
<router-view></router-view>
</keep-alive>
3、使用exclude来指定不需要缓存的组件 其他的都需要缓存
<keep-alive exclude="Cart,My">
<router-view></router-view>
</keep-alive>
4、如果我们缓存了大量的组件 反而会造成内存占用和浪费 因此可以使用 max来设定最多缓存多少个组件
<keep-alive :max="3">
<router-view></router-view>
</keep-alive>
5、可以使用路由配置来 设置 每个路由组件是否需要缓存了
<keep-alive>
<router-view v-if="$route.meta.isKeep"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.isKeep"></router-view>
6、使用了keep-alive 组件会多2个生命周期函数:
activated :做一些时效性比较高的行为
activated() {
console.log('Category激活');
},
deactivated() {
console.log('Category失活');
},
-----------------------
mode : 模式
const router = new VueRouter({
routes,
mode : 'history' // hash 默认 history
})
history:url 不带 # 部署模式必须配伪静态
hash : 默认 带 # 部署模式 url访问出问题的概率小
hosts文件目录:C:\Windows\System32\drivers\etc\hosts
-----------------------
路由守卫:
它的思想来自于后端框架中的一种叫“中间件”思想。
类似于生命周期,它会在特定下情况下执行特定方法名 方法
全局前置守卫 -- 每次路由跳转都可以执行
to: 即将访问的路由相关信息 下一步 this.$route
from : 当前正在访问的路由相关信息 即将离开的利用 当前的 this.$route
next: 函数 当前路由跳转 放行方式
-- next() next(true) :放行 马上执行 to对应组件
-- next(false) :不做任何放行处理 继续停留在from当前路由中
-- next('/login') next({name:'Login'}) : 不执行to 重定向到另外一个路由中 它重定向语法和push一致
router.beforeEach((to, from, next) => {
if (!window.sessionStorage.getItem('token') && to.meta.isLogin) {
return next('/login?url=' + to.fullPath)
}
document.title = to.meta.title;
return next()
})
----------------------------------------------
vuex :
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
多个任意组件关系中数据共享。
v3 => vue2
v4 => vue3
手动安装:
1:安装
npm install vuex@3 --save
2、store/index.js 定义vuex全局状态管理具体业务里面 state、mutations、acitons、getters
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0,
msg : 'aa',
menu: null
},
mutations: {
// state:对象 当前所有state的最新值
// params:调用当前mutation方法传递的参数
countJia(state, params) {
state.count += params
},
countJian(state, params) {
state.count -= params
}
},
actions: {
// 第一个参数.state:当前所有state的最新值
// 第一个参数.commit 用来调用mutation方法的
// 第一个参数.dispatch 用来调用其他action方法的
changeCount({state,commit,dispatch}, params) {
setTimeout(() => {
let num = Math.round(Math.random() * 10)
commit('countJia', num)
}, 1000)
}
},
getters: {
countPf(state) {
return state.count ** 2
}
}
})
export default store;
3、main.js
import store from './store'
new Vue({
store, // 其他组件中就可以通过 this.$store 来获取到Store实例
render: h => h(App)
}).$mount('#app')
-------------------------
state:
方式一:
模板中:
{{$store.state.count}} 不推荐的 以后uniapp如果这样搞 微信小程序会有兼容问题 应该使用方式二或方式三
js中:
this.$store.state.count
方式二:自定义计算属性
computed: {
count() {
return this.$store.state.count
}
}
方式三:使用mapState 快速生成本地计算属性
直接从this.$store.state返回,而没有其他更多业务或计算;如果有更多业务或计算请使用方式二自己手写计算属性
import {mapState} from 'vuex'
computed: {
...mapState(['count', 'msg']),
...mapState({
mycount: 'count',// 本地计算属性名:state中变量名
mymsg: 'msg'
})
}
生成的计算属性名,如果不换名字用数组,换名字用对象
mutations:
方式一:
this.$store.commit('mutation方法名', 参数)
方式二:使用mapMutations 快速生成本地方法
如果是直接通过this.$store.commit理解调用对应的mutation方法,没有其他更多业务判断才可以使用辅助;如果需要更多判断(验证),就只能自己根据情况调用mutation方法
methods:{
countJia(num) {
this.$store.commit('countJia', num)
},
countJian(num) {
this.$store.commit('countJian', num)
},
...mapMutations(['countJia', 'countJian']),
...mapMutations({
myjia: 'countJia',
myjian: 'countJian'
}),
},
actions:
方式一:
this.$store.dispatch('action方法', 参数)
方式二:
...mapActions({
mychange : 'changeCount' // 不改名字用数组 ,改名字对象
})
getters:
方式一:
模板中:
{{$store.getters.countPf}}
js中:
this.$store.getters.countPf
方式二:自定义计算属性
countPf() {
return this.$store.getters.countPf
}
方式三:使用mapGetters 辅助
computed: {
countPf() {
return this.$store.getters.countPf
},
...mapGetters(['countPf']) // 不换名字用数组 换名字用对象
}