VUE学习
vue-router
vue-router是用作前端路由的。
安装vue-router
npm install vue-router --save
编写vue-router的配置文件
在src目录下新建一个router的配置文件router.js (名字自定义):
// 导入vue
import Vue from 'vue'
// 导入vue-router
import Router from 'vue-router'
// 导入需要路由的组件
import Hello from './components/hello/Hello'
// 设置vue-router组件全局使用
Vue.use(Router)
// 配置组件路由参数信息
const routes = [
{
// 组件路由路劲
path: '/hello',
// 要路由的组件
component: Hello,
// 取别名,名字自定义
name: 'Hello'
}
]
// 构建路由配置对象
const router = new Router({
routes
})
// 导出配置
export default router
使vue-router配置生效
在main.js中,导入上面配置好的路由信息
import Vue from 'vue'
import App from './App'
// 导入router的配置
import router from './router'
new Vue({
// 使配置生效
router,
render: h => h(App)
}).$mount('#app')
重启项目,通过ip+端口+ /hello 就能访问到对应的Hello组件了。
配置多级路由
import Vue from 'vue'
import Router from 'vue-router'
import Hello from './component/Hello'
import Hi from './component/hi'
//全局使用router
Vue.use(Router)
const routes = [{
{
path: '/hello',
component: Hello,
name: 'Hello',
// 每个路由都有一个children标签,用于配置子路由
children: [
{
path: '/hi',
component: Hi,
name: 'Hi'
}
]
}
}]
const router = new Router({
routes
})
export default routes
子路由,其实 就是路由下的一个children属性,在children属性是一个数组,可以配置多个路由,在这个属性中的路由中,还可以配置children属性,达到配置多级路由的效果。
使用vue-router
配置好路由信息后,可以通过router-link制作导航,to属性对应配置的path的路径。router-view用来加载(显示)要路由的模板。
<!--配置路由路径-->
<router-link to="/hello">hello</router-link>
<!--配置路由模板显示地址-->
<router-view></router-view>
也可以通过路由配置中的name属性实现跳转:
<!-- to前面一定要写:,只是一个对象,name: 定义的名字,这样就会跳转到指定name的组件上-->
<router-link :to="{name: 'Hello'}"></router-link>
<router-view></router-view>
在组件中传值
注意的是,to前面一定要有:,to的值是一个对象,并且属性是name, params:
<router-link :to="{name: 'hi', params: {username: 'tom', age: 18} }"></router-link>
在组件中接收参数要用到**$route**:
<p> {{ $route.name }} </p>
<p> {{ $route.params }} </p>
在不同页面加载不同的组件
配置路径对应的组件,配置router:
import Vue from 'vue'
import Router from 'vue-router'
import Student from './views/Students'
import Teacher from './views/Teacher'
Vue.use(Router)
const routes = [{
path: '/user',
// /user路径下对应了两个组件
components: {
Student,
Teacher
}
}]
const router = new Router({
routes,
mode: 'history'
})
export default router
使用时,在router-view中指定要显示的是哪个组件:
<template>
<div id="app">
app
<hr>
<router-link to="/user">load</router-link>
<hr>
<!--通过name属性指定当前router-view要显示的组件-->
<router-view name="Teacher"></router-view>
<hr>
<router-view name="Student"></router-view>
</div>
</template>
通过url传递参数
在定义路由时,要指定传递的url参数名。
const routes = [{
path: '/user',
components: {
Student,
Teacher
}
}, {
// 指定参数名,参数名后面加(),里面写正则表达式,可以匹配路径
path: '/hello/:id(\\d+)/:name',
component: Hello
}]
路径跳转:
<!-- 最终路径显示成:http://192.168.56.1:8081/hello/122/xx -->
<router-link to="/hello/122/xx">URL</router-link>
<hr>
<router-view></router-view>
在组件中获取参数:
<p> {{$route.params.id}} </p>
<p> {{$route.params.name}} </p>
路由重定向
路由重定向只需要在路由配置里面加redirect就可以了,重定向也可以携带url参数:
{
path: '/hi/:id',
redirect: '/hello/:id'
}
为路径去别名
使用路由时在router-link的to属性中可以写hi,也可以写/hello,注意不要对根路径/取别名:
{
path: '/hi',
redirect: '/hello',
alias: '/hello';
}
路径*匹配
如果有个路径匹配不到,跳转到404页面,注意路径是从上向下匹配的,* 这个匹配应该放到路由最后:
{
path: '*',
component: FileNotFound
}
路由独享守卫
路由钩子函数、守卫,可以控制路由的访问,只要beforeEnter :
{
path: '/hello',
component: Hello,
name: 'hello',
// 定义路由信息的时候指定
beforeEnter (to, from, next) {
console.log("去到", to.fullPath);
console.log("来自", from.fullPath);
// 当调用next()或者next(true)的时候,路由正常跳转
next(true);
}
}
组件内守卫
钩子函数(守卫)写在组件中, beforeRouteEnter进入路由前,beforeRouteLeave离开组件前:
// 在组件中
export default {
name: 'Hello',
beforeRouteEnter(to, from, next) {
console.log("去", to.fullPath)
console.log("来自", from.fullPath)
next(true)
},
beforeRouteLeave(to, from, next) {
console.log("去", to.fullPath)
console.log("来自", from.fullPath)
next(true)
}
}
全局守卫
前置钩子函数:
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
后置钩子函数,不接受next,不会改变导航本身:
router.afterEach((to, from) => {
// ...
})
动态路由
this.$router.push()
<!--绑定一个事件,调用toHello方法-->
<button @click="toHello">load</button>
<script>
export default {
name: "App",
methods: {
toHello() {
// 在toHello方法中调用push()方法,方法接收一个参数,路由地址
this.$router.push('/hello')
}
}
}
</script>
this.$router.go()
<button @click="toHello">load</button>
<script>
export default {
name: "App",
methods: {
toHello() {
// 在toHello方法中调用go()方法,方法接收一个参数,历史记录数,-1表示回退一个历史记录,-2表示回退2个历史,同理整数表示前进
this.$router.go()
}
}
}
</script>
this.$router.repalce()
<button @click="toHello">load</button>
<script>
export default {
name: "App",
methods: {
toHello() {
// 在toHello方法中调用replace()方法,方法接收一个参数,路由地址,比如当前是路由时/a,我们触发这个方法执行,跳转到/hello,replace方法会替换/a,变成/hello,/a不出现在历史记录中,所以回退的时候不会回退到/a
this.$router.replace('/hello')
}
}
}
</script>
Vuex
简单使用
安装vuex
npm install vuex --save
在src下新建store.js
// 引入vue
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 使用vuex
Vue.use(Vuex)
// 声明状态
const state = {
count: 1
}
// 声明变化
const mutations = {
// 这里对状态中的count修改
add(state) {
state.count++
},
reduce(state) {
state.count--
}
}
// 创建vuex数据仓库,需要state和mutations两个属性
const store = new Vuex.Store({
state,
mutations
})
// 暴露仓库
export default store
在组件中引用:(this.$store.commit() 接受mutations中定义的函数,会将接收的函数执行)
<template>
<div>
<!--调用当前实例的store属性,取出state状态中的count-->
Count: {{this.$store.state.count}}<br/>
<!--this.$store.commit接收一个mutations中定义的函数,用户操作state中的数据,这里不能用this调用-->
<button @click="$store.commit('add')">+</button>
<button @click="$store.commit('reduce')">-</button>
</div>
</template>
<script>
// 引入数据仓库
import store from './store'
export default {
name: 'Count',
// 作为当前vue实例属性
store
}
</script>
使用vuex的state中的属性
方式一: 通过$store.state.xxx
访问,xxx就是你要访问的数据
<template>
<div>
Count: {{$store.state.count}}<br/>
</div>
</template>
<script>
// 引入数据仓库
import store from './store'
export default {
name: 'Count',
// 作为当前vue实例属性
store
}
</script>
方式二:通过计算属性访问,其实也是调用了$store.state.xxx
<div>
{{ count }}
</div>
<script>
import store from './store'
export default {
name: 'Count',
computed: {
// 计算属性中使用
count() {
return this.$store.state.count;
}
},
store
}
</script>
方式三:vue 提供了 mapState 函数,它把state 直接映射到我们的组件中。
<template>
<div>
Count:{{ count }}<br/>
</div>
</template>
<script>
import store from './store'
// 获取mapState
import { mapState } from 'vuex'
export default {
name: 'Count',
// 映射到组件
computed: mapState(['count']),
store
}
</script>
上面的方式不能自己写其他计算属性了,如果要写其他计算属性,可以用下面的写法:
computed: {
localComputed() {
},
// 映射
...mapState({
count: 'count'
})
},
修改state中的状态
修改状态state需要用到mutations属性,mutations中定义函数,函数的第一个参数时默认的,为state,第二个参数可以是一个对象。可以通过state获取state中的属性
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 3
}
// 定义操作state的函数
const mutations = {
// 第一个参数是默认的,之后的参数是自定义的
add(state, n) {
state.count += n
},
reduce(state, obj) {
state.count = state.count + obj.n + obj.m
}
}
const store = new Vuex.Store({
state,
// 在mutations中定义一些函数操作state
mutations
})
调用定义的函数操作state:
<button @click="$store.commit('add', 10)">+</button>
<button @click="$store.commit('reduce', {n: 10, m: 20})">-</button>
<script>
import store from './store'
import { mapState } from 'vuex'
export default {
name: 'Count',
store
}
</script>
使用mapMutations:
<template>
<div>
Count: {{$store.state.count}}<br/>
<button @click="add(11)">+</button>
<button @click="reduce({n: 10, m: 20})">-</button>
</div>
</template>
<script>
import store from './store'
// 引入mapMutations
import { mapMutations } from 'vuex'
export default {
name: 'Count',
// 传入方法名即可
methods: mapMutations(['add', 'reduce']),
store
}
</script>
为了能自定义方法,也可以这样写:
<template>
<div>
Count: {{$store.state.count}}<br/>
<button @click="add(11)">+</button>
<button @click="reduce({n: 10, m: 20})">-</button>
</div>
</template>
<script>
import store from './store'
import { mapMutations } from 'vuex'
export default {
name: 'Count',
methods: {
// 自定义方法
my() { },
// mapNuutations的用法
...mapMutations(['add', 'reduce'])
},
store
}
</script>
getters
设置getters
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 3
}
const mutations = {
add(state, n) {
state.count += n
},
reduce(state, obj) {
state.count = state.count + obj.n + obj.m
}
}
// 定义getters
const getters = {
count(state) {
return state.count += 100
}
}
const store = new Vuex.Store({
state,
mutations,
// 使用getters
getters
})
export default store
使用getters:
<template>
<div>
<!--要通过这种方式 访问-->
Count: {{count}}<br/>
</div>
</template>
<script>
import store from './store'
// 引入getters
import { mapMutations, mapGetters } from 'vuex'
export default {
name: 'Count',
methods: {
my() { },
...mapMutations(['add', 'reduce'])
},
// 在计算属性中使用..
computed: {
// 使用getters
...mapGetters(['count'])
},
store
}
</script>
action异步执行
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 3
}
// 定义方法
const mutations = {
add (state, n) {
state.count += n
},
reduce (state, obj) {
state.count = state.count - obj.n - obj.m
}
}
// 声明action,声明要异步执行的函数
const actions = {
// 传入的是context对象
add (context) {
context.commit('add', 0.1)
},
// 或者是{commit}
reduce({commit}, n) {
commit('reduce', n )
}
}
const store = new Vuex.Store({
state,
mutations,
actions
})
export default store
使用:
<template>
Count: {{count}}<br/>
<button @click="add">+</button>
<button @click="reduce({n: 1, m :2})">-</button>
</template>
<script>
import store from './store'
// 导入
import { mapActions, mapState } from 'vuex'
export default {
name: 'Count',
methods: {
my () {
},
// 使用
...mapActions(['add', 'reduce'])
},
computed: {
...mapState(['count'])
},
store
}
</script>