vue-click的传值、路由配置以及koa2的基本操作
vue-cli组件之间的传值
1.父子组件之间的传值
1.1父组件向子组件传值
在父组件中引入子组件
import com from './components/com'
export default {
data() {
return {
msg:20
}
},
name: 'App',
components: {
com,
},
}
用v-bind(:)对子组件进行传值
<com :age='msg'></com>
在子组件中进行调用
<h1>这是子组件</h1>
<h1>{{age}}</h1>
执行结果
1.2 子组件向父组件传值
父组件创建一个方法
methods: {
add(data){
console.log(data)
}
},
子组件进行绑定
<com :age='msg' @func='add'></com>
子组件使用$emit进行传值
//func为父组件中绑定方法定义的名字
//name为要传递的参数
<button @click='$emit("func",name)'>点击传值</button>
执行结果
或者在父组件中定义一个变量,将子组件传递过来的参数赋值给变量,展示在页面上
export default {
data() {
return {
msg:20,
name:""
}
},
name: 'App',
components: {
com,
},
methods: {
add(data){
// console.log(data)
this.name=data
}
},
}
执行结果
2.兄弟组件之间的传值(vuex)
1. vuex简介
vuex是专门用来管理vue.js应用程序中状态的一个插件。他的作用是将应用中的所有状态都放在一起,集中式来管理。
2. vuex的组成结构示意图
vuex的特点是把数据单独隔离,形成一棵树状图。单独隔离就意味着它有自己的生态系统。输入和输出,其中action作为数据的输入,state作为数据的输出。如下图:
vuex里有这么一个规则:
只能在mutaions里修改state,actions不能直接修改state
mutations即变化,修改state的数据,而且只能是同步的,不能存在异步的操作。如果需要异步怎么办呢?把异步操作放在actions里,拿到数据再通过mutations同步处理。
3. vuex 的核心概念
3.1 store
vuex 中最关键的是store对象,这是vuex的核心。
可以说,vuex这个插件其实就是一个store对象,
每个vue应用仅且仅有一个store对象。
- 3.1.1 创建store
const store = new Vuex.Store({...});
store是Vuex.Store这个构造函数new出来的实例。在构造函数中可以传一个对象参数。这个参数中可以包含5个对象:
- state – 存放状态
- getters – state的计算属性
- mutations – 更改状态的逻辑,同步操作
- actions – 提交mutation,异步操作
- mudules – 将store模块化
关于store,需要先记住两点:
- store 中存储的状态是响应式的,当组件从store中读取状态时,如果store中的状态发生了改变,那么相应的组件也会得到更新;
- 不能直接改变store中的状态。改变store中的状态的唯一途径是提交(commit)mutations。这样使得我们可以方便地跟踪每一个状态的变化。
3.1.2 一个完整的store的结构是这样的
const store = new Vuex.Store({
state: {
// 存放状态
},
getters: {
// state的计算属性
},
mutations: {
// 更改state中状态的逻辑,同步操作
},
actions: {
// 提交mutation,异步操作
},
// 如果将store分成一个个的模块的话,则需要用到modules。
//然后在每一个module中写state, getters, mutations, actions等。
modules: {
a: moduleA,
b: moduleB,
// ...
}
});
3.2 state
state上存放的就是变量。没有使用 state 的时候,我们都是直接在 data 中进行初始化的,但是有了 state 之后,我们就把 data 上的数据转移到 state 上去了。另外有些状态是组件私有的状态,称为组件的局部状态,我们不需要把这部分状态放在store中去。
如何在组件中获取state的值
- 1、在store.js文件里增加一个常量对象。store.js文件就是引入vuex时的那个文件。
const state = {
count:1
}
- 2、用export default 封装代码,让外部可以引用。
export default new Vuex.Store({
state
});
- 3、新建一个vue的模板,位置在components文件夹下,名字叫count.vue。在模板中我们引入我们刚建的store.js文件,并在模板中用
{{$store.state.count}}
输出count 的值。
<template>
<div>
<h2>{{msg}}</h2>
<hr/>
<h3>{{$store.state.count}}</h3>
</div>
</template>
<script>
import store from '@/vuex/store'
export default{
data(){
return{
msg:'Hello Vuex',
}
},
store
}
</script>
3.3mutations
mutations里面是如何更改state中状态的逻辑。更改Vuex中的state的唯一方法是,提交mutation,即store.commit(‘increment’)
。
提交载荷(payload)
可以向commit传入额外的参数,即mutation的载荷。
store.js文件:
const mutations = {
add(state, params) {
state.count += params
},
delet(state) {
state.count--
}
}
const actions = {
add: ({ commit }, params) => {
commit('add', params)
},
delet: ({ commit }) => {
commit('delet')
}
}
com.vue文件
{{$store.state.count}}
//调用方法时进行传参
<button @click='add(3)'>增加</button>
<button @click='delet'>减少</button>
3.4actions
因为mutations中只能是同步操作,但是在实际的项目中,会有异步操作,那么actions就是为了异步操作而设置的。这样,就变成了在action中去提交mutation,然后在组件的methods中去提交action。只是提交actions的时候使用的是dispatch函数,而mutations则是用commit函数。
一个简单的action
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 0
}
const mutations = {
add(state, params) {
state.count += params
},
delet(state) {
state.count--
}
}
const actions = {
add: ({ commit }, params) => {
commit('add', params)
},
delet: ({ commit }) => {
commit('delet')
}
}
export default new Vuex.Store({
state,
mutations,
actions
})
在组件中分发action
import {mapActions} from 'vuex'
export default {
methods:mapActions([
'add',
'delet'
])
}
mudules
module是为了将store拆分后的一个个小模块,这么做的目的是因为当store很大的时候,分成模块的话,方便管理。
4.1 每个module拥有自己的state, getters, mutation, action
const moduleA = {
state: {...},
getters: {...},
mutations: {....},
actions: {...}
}
const moduleB = {
state: {...},
getters: {...},
mutations: {....},
actions: {...}
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
});
store.state.a // 获取moduleA的状态
store.state.b // 获取moduleB的状态
案例:
模块a(a.js)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 0
}
const mutations = {
add(state) {
state.count++
},
del(state) {
state.count--
}
}
const actions = {
add: ({ commit }) => {
commit('add')
},
del: ({ commit }) => {
commit('del')
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
模块b(b.js)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
money: 0
}
const mutations = {
add(state) {
state.money++
},
del(state) {
state.money--
}
}
const actions = {
add: ({ commit }) => {
commit('add')
},
del: ({ commit }) => {
commit('del')
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
创建store对象(index.js)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import count from './a'
import money from './b'
export default new Vuex.Store({
modules: {
count,
money
}
})
入口文件(main.js)
import store from './store/index'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
storeConfig,
router,
store
}).$mount('#app')
a组件(a.vue)
<template>
<div>
<h1>{{$store.state.count.count}}</h1>
<button @click='add'>增加</button>
<button @click='del'>减少</button>
</div>
</template>
<script>
import {mapActions} from 'vuex'
export default {
methods:mapActions('count',[
'add',
'del'
])
}
</script>
<style>
</style>
b组件(b.vue)
<template>
<div>
<h1>{{$store.state.money.money}}</h1>
<button @click='add'>增加</button>
<button @click='del'>减少</button>
</div>
</template>
<script>
import {mapActions} from 'vuex'
export default {
methods:mapActions('money',[
'add',
'del'
])
}
</script>
<style>
</style>
app.vue
import count from './components/a'
import money from './components/b'
components: {
count,
money
},
==注意:==导出时需要添加namespaced: true
,否则会报错
路由配置
登录注册案例:
1.新建登录注册的组件
以登录为例:
<template>
<div>
<h1>这是登录界面</h1>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
2.进行路由分配,新建router.js文件
import Vue from "vue"
import VueRouter from "vue-router"
Vue.use(VueRouter)
//导入登录注册的组件
import login from '../components/login.vue'
import register from '../components/register.vue'
const routes = [{
path: '/login',
component: login
}, {
path: '/register',
component: register
}]
export default new VueRouter({
routes
})
3.入口文件main.js引入路由文件
import router from './router/router'
new Vue({
render: h => h(App),
router
}).$mount('#app')
4.app.vue内显示
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
koa2
koa是什么?
koa是基于nodejs的一个http中间件框架。koa源码只有一千多行,所有的功能都可以通过插件实现,简单易懂,自由度高。
安装
cnpm i koa2 my_object
目录
中间件
1. 中间件是什么?
中间件(middleware)本质上就是一个函数,
处于http request和http response中间,实现某种中间的功能。
使用app.use()来加载中间件。koa中每个中间件默认两个参数,
第一个是ctx对象,第二个是next函数。
我们可以使用next函数来把执行权转交给下一个中间件。
2. 中间件栈
多个中间件会形成一个栈结构,以"先进后出"的原则执行。
const one = (ctx, next) => {
console.log('1');
next();
console.log('2');
}
const two = (ctx, next) => {
console.log('3');
next();
console.log('4');
}
const three = (ctx, next) => {
console.log('5');
next();
console.log('6');
}
app.use(one);
app.use(two);
app.use(three);
// 1 3 5 6 4 2
3. 移除next?
中间件通过next来将函数执行权移交到下一个中间件,若无next,执行权就不会移交下一个中间件,后续中间件无效。
app.use((crx, next) => {
console.log(1)
next()
console.log(2)
})
app.use((crx, next) => {
console.log(3)
// next()
console.log(4)
})
app.use((crx, next) => {
console.log(5)
next()
console.log(6)
})
app.listen(3000);
// 1 3 4 2
自定义中间件
pv.js中间件代码:
function pv(ctx) {
console.log(ctx.path)
}
module.exports = function() {
return async function(ctx, next) {
pv(ctx);
await next();
}
}
入口文件进行调用:
const pv = require('./middleware/pv')
app.use(pv())
use
- 每一次use传入一个回调函数f,listen时执行这个函数f,demo的回调函数f是
(ctx) => {
ctx.body = 'Hello Koa';
}
- 回调函数f一共有两个参数,分别是context(以下简写ctx)和next。第一个参数ctx是原生req、res经过一系列处理后产生的对象。
函数f的第二个参数next()跳到下一个回调函数,多个use的回调函数按照顺序执行。
listen
listen的实现原理其实就是对http.createServer进行了一个封装,重点是这个函数中传入的callback。callback就是所有中间件的组合。
listen(...args) {
const server = http.createServer(this.callback());
return server.listen(...args);
}
ctx
koa中, ctx表示一次对话的上下文(包括 HTTP 请求和 HTTP 回复)。为了开发方便而设计的一个js对象,绑定了请求和响应相关的数据和方法(如ctx.path、ctx.body等)。本质上使用request、response两个文件拓展属性,ctx通过delegate实现代理拿到request和response的方法和属性。
异步处理Async 、Await和Promise 的使用
概念
- async是让方法变成异步形式。
- await是等待异步方法执行完成,将异步方法变为同步,所以await使用会受到约束,需要在async方法下使用。
async
让方法变成异步,执行下面node代码时,会输出Promise{‘Hello async’},返回为Promise。
注意:await 必须在 async 方法中才可以使用因为 await 访问本身就会造成程序停止堵塞,所以必须在异步方法中才可以使用。
await 在等待 async 方法执行完毕,其实 await 等待的只是一个表达式,这个表达式在官方文档里说的是 Promise 对象,但是它也可以接受普通值。
async/await 同时使用
async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而
await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。
也就是说await需要在async方法中才能有效。
举例:
router.get('/test', async(ctx) => {
console.log(new Date().getTime());
const a = await new Promise((resolve, project) => {
setTimeout(() => {
console.log('123 === ')
}, 1000)
resolve('a')
});
const b = await 10;
const c = await new Promise((solve, project) => {
solve("c")
})
ctx.body = {
a,
b,
c
}
})
页面显示: