1.代理服务器
第一台服务器server1代码如下:
const express = require('express')
const app = express()
app.use((request,response,next)=>{console.log('有人请求服务器1了')console.log('请求的资源是:', request.url);//console.log('请求来自于:', request.get('Host'));next()
})app.get('/students' , (request, response)=>{const students = [{id:'001',name:'张三', age:12},{id:'002',name:'李四', age:13},{id:'003',name:'王二', age:14},]response.send(students)
})app.listen(5000,(err)=>{if (!err) console.log('服务器1启动成功了,请求学生信息地址为:http://localhost:5000/students')
})
const express = require('express')
const app = express()
app.use((request,response,next)=>{console.log('有人请求服务器1了')console.log('请求的资源是:', request.url);//console.log('请求来自于:', request.get('Host'));next()
})app.get('/students' , (request, response)=>{const students = [{id:'001',name:'张三', age:12},{id:'002',name:'李四', age:13},{id:'003',name:'王二', age:14},]response.send(students)
})app.listen(5000,(err)=>{if (!err) console.log('服务器1启动成功了,请求学生信息地址为:http://localhost:5000/students')
})
第二台服务器server2代码如下:
const express = require('express')
const app = express()
app.use((request,response,next)=>{console.log('有人请求服务器2了')//console.log('请求的资源是:', request.url);//console.log('请求来自于:', request.get('Host'));next()
})app.get('/cars' , (request, response)=>{const cars = [{id:'001',name:'红旗', num:12},{id:'002',name:'BYD', num:13},{id:'003',name:'特斯拉', num:14},]response.send(cars)
})app.listen(5001,(err)=>{if (!err) console.log('服务器2启动成功了,请求学生信息地址为:http://localhost:5001/car')
})
App代码如下:
<template>
<!-- <div id="app"><!–router-link:相当于<a>标签,其中的to属性为要指定的路径router-view:主要是将路由与组件进行匹配–><router-link to="/main">这是Mian首页</router-link><router-link to="/content">这是Content内容页</router-link><router-view></router-view><h1 v-text="msg" ref="tittle"></h1><button @click="showDom">点我输出上方的信息</button><School/><br/>
<!– 带冒号进行绑定,绑定的是字符串里的int数据,不带则是字符串数据18 –><Student></Student></div>--><div class="app"><button @click="getStudent">点击请求学生数据</button><button @click="getCars">点击请求汽车数据</button></div>
</template><script>
import School from "./components/School";
import Student from "./components/Student";
import test from "./components/conpenent1/test"
import test02 from "./components/conpenent1/test02";
import test03 from "./components/conpenent1/test03";
import axios from 'axios'
export default {name: 'App',components: {test,test02,test03},data(){return{msg:'你好啊!',}},methods:{getStudent(){axios.get('/api/students').then(response =>{console.log("请求成功了", response.data)},error=>{console.log('请求失败了',error.message)})},getCars(){axios.get('/demo/cars').then(response =>{console.log("请求成功了", response.data)},error=>{console.log('请求失败了',error.message)})}}
}
</script><style>.app{background-color: gray;padding: 5px;}
</style>
注意:当你的项目是webpack项目时,没有vue.config.js配置文件,因此需要在当前项目的build目录下的webpack.base.conf.js文件中配置代码,即增加一个devServer配置项,配置代码如下:
devServer: {proxy: {'/api': {target: 'http://localhost:5000',ws: true, // 代理websocketschangeOrigin: true,pathRewrite: {'^/api' : ''} //用于控制请求头中的host值},'/demo': {target: 'http://localhost:5001',ws: true,pathRewrite: {'^/demo' : ''}}}}
VueX学习
**概念:**在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),
也是一种组件间通信的方式,且适用于任意组件间通信。
语法格式如下:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex)
//准备actions - 用于响应组件中的动作
const actions = {}
//准备mutations- 用于操作数据(state)
const mutations = {}
//准备state- 用于存储数据
const state = {}//创建store
export default new Vuex.Store({actions, mutations,state})
作用:(通过store对所有的Actions、Mutation和State进行统一管理)
-
多组件状态共享
解决深层嵌套组件或兄弟组件间的数据传递难题(如跨三级组件共享用户权限数据)。 -
响应式状态管理
自动同步所有依赖该状态的视图更新(如购物车商品数量变化时,导航栏/结算页同步刷新)。 -
可预测的状态流
强制通过 mutation 修改数据,结合 DevTools 实现时间旅行调试(可回退到任意状态快照)。 -
集中式调试
通过浏览器插件Vue Devtools实时追踪状态变更路径,支持状态快照导入导出。
Mutation的作用:
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。
Action作用:
Action和Mutation相似,一般不用Mutation 异步操作,若要进行异步操作,使用Action原因:为了方便devtools打个快照存下来,方便管理维护。所以说这个只是规范,而不是逻辑的不允许,只是为了让这个工具能够追踪数据变化而已
state的作用:提供唯一的公共数据源,所有共享的数据统一放到store的state进行储存,相似与data。
getter的作用:类似于vue中的computed,进行缓存,对于Store中的数据进行加工处理形成新的数据。
Modules的作用:当遇见大型项目时,数据量大,store就会显得很臃肿,为了解决问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
原理如下:
没有使用VueX的代码案例:
<template><div><h1>当前求和为:{{sum}}</h1><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="increment">+</button><button @click="decreament">-</button><button @click="incramentOdd">当前求和为奇数再加</button><button @click="increamentWait">等等再加</button></div>
</template><script>
export default {name: "Cout",data(){return {sum: 0,n:1}},methods:{increment(){this.sum += this.n},decreament(){this.sum -= this.n},incramentOdd(){if (this.sum %2){this.sum += this.n}},increamentWait(){setTimeout(()=>{this.sum +=this.n },1000)},}
}
</script><style scoped>
button{margin-right: 8px;
}
</style>
使用Vuex的代码如下:
1.store下的index.js的代码如下:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex)
//准备actions - 用于响应组件中的动作,做业务逻辑
const actions = {jia(context,value){console.log('进入了jia')context.commit('JIA',value)},jian(context,value){context.commit('JIAN',value)},jiaOdd(context,value){if (context.state.sum%2){context.commit('JIA',value)}},jiaWait(context,value){setTimeout(()=>{context.commit('JIA',value)},1000)}
}
//准备mutations- 用于操作数据(state)
const mutations = {JIA(state,value){console.log('进入了JIA')state.sum += value},JIAN(state,value){state.sum -= value},
}
//准备state- 用于存储数据
const state = {sum : 0,school:'武汉大学',subject:'Vue前端框架'
}
//准备getters-用于将state中的数据进行加工
const getters = {bigsum(state){return state.sum * 10}
}//创建store
export default new Vuex.Store({actions, mutations,state,getters})
2.count文件中代码如下:
<template><div>
<!-- <h1>当前求和为:{{$store.state.sum}}</h1>-->
<!-- <h1>当前求和放大十倍为:{{$store.getters.bigsum}}</h1>-->
<!-- <h1>我在{{$store.state.school}}学习{{$store.state.subject}}</h1> --><h1>当前求和为:{{he}}</h1><h1>当前求和放大十倍为:{{bigsum}}</h1><h1>我在{{xuexiao}}学习{{xueke}}</h1><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="increment(n)">+</button><button @click="decreament(n)">-</button><button @click="incramentOdd(n)">当前求和为奇数再加</button><button @click="increamentWait(n)">等等再加</button></div>
</template><script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex' //注意,导入时要加大括号export default {name: "Cout",data(){return {n:1}},computed:{//借助mapState生成计算属性,从state中读取数据(对象写法)...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),//...mapState将对象展开he:'sum、xuexiao:school、xueke:'subject'//借助mapState生成计算属性,从state中读取数据(数组写法)//...mapState(['sum' ,'school', 'subject']) //通过mapState生成名称为数组中对应的名称的方法//...mapGetters({bigsum:'bigsum'}),...mapGetters(['bigsum'])},methods:{
/* increment(){this.$store.dispatch('jia',this.n)},decreament(){this.$store.dispatch('jian', this.n)},*///借助mapMutations生成对应的方法,方法中会调用commit去联系mutation(对象写法)...mapMutations({increment:'JIA',decreament:'JIAN'}),//...mapMutations(['JIA','JIAN']),//使用数组的方式,但是template里对应的标签需要改为相同的名字//==============================================/*incramentOdd(){this.$store.dispatch('jiaOdd',this.n)},increamentWait(){this.$store.dispatch('jiaWait',this.n)},*/...mapActions({incramentOdd:'jiaOdd',increamentWait:'jiaWait'}),// ...mapActions(['jiaOdd','jiaWait'])},mounted() {console.log(this)}
}
</script><style scoped>
button{margin-right: 8px;
}
</style>
3.main.js文件代码如下:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue' // 引入Vue
import App from './App' // 引入App
// import VueRouter from 'vue-router'
// Vue.use(VueRouter);Vue.config.productionTip = false //来关闭生产模式下给出的提示
import router from './router' //自动扫描其下的路由配置
import plugins from './plugins' //导入插件import store from "./components/store";
Vue.use(plugins) //使用插件new Vue({ //创建Vue实例对象el: '#app',render: h=>h(App),router,store,components:{App},template:'<App/>',beforeCreate() {Vue.prototype.$bus=this //安装全局事件总线},mounted() {console.log(this.Store)}
})
四个map方法的使用
1.mapState方法:用于帮助我们映射 state 中的数据为计算属性
computed:{//结组mapState生成计算属性:sum、school、subject(对象写法)...mapState({sum:'sum',school:'school',subject:'subject'}),//借助mapstate生成计算属性:sum、school、subject(数组写法)...mapState(['sum','school','subject'])
}
2.mapGetters方法:用于帮助我妹映射getters中的数据为计算属性
computed:{//借助mapGetters生成计算属性:bigsum(对象写法)...mapGetters({bigSum:'bigSum'})//借助mapGetters生成计算属性:bigsum(数组写法)...mapGetters(['bigSum'])}
3.mapActions方法:用于帮助我们生成与 actions对话的方法,即:包含$store.dispatch(xxx)的函数
methods:{//靠mapActions生成:incrementOdd、incrementWait(对象形式)...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})//靠mapActions生成:incrementOdd、incrementWait(数组形式)...mapActions(['jiaOdd','jiawait'])
}
4.mapMutations方法:用于帮助我们生成与 mutations对话的方法,即:包含$store.commit(xxx)的函数
methods:{//靠mapActions生成:increment、decrement(对象形式)...mapMutations({increment:'JIA',decrement:'JIAN'})//靠mapMutations生成:JIA、JIAN(对象形式)...mapMutations(['JIA','JIAN']),
}
注意:mapAcions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象
多文件共享数据
Count.vue代码如下:
<template><div>
<!-- <h1>当前求和为:{{$store.state.sum}}</h1>-->
<!-- <h1>当前求和放大十倍为:{{$store.getters.bigsum}}</h1>-->
<!-- <h1>我在{{$store.state.school}}学习{{$store.state.subject}}</h1> --><h1>当前求和为:{{he}}</h1><h1>当前求和放大十倍为:{{bigsum}}</h1><h1>我在{{xuexiao}}学习{{xueke}}</h1><h3>总人数时:{{persons.length}}</h3><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="increment(n)">+</button><button @click="decreament(n)">-</button><button @click="incramentOdd(n)">当前求和为奇数再加</button><button @click="increamentWait(n)">等等再加</button></div>
</template><script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex' //注意,导入时要加大括号export default {name: "Cout",data(){return {n:1}},computed:{//借助mapState生成计算属性,从state中读取数据(对象写法)...mapState({he:'sum',xuexiao:'school',xueke:'subject',persons:'persons'}),//...mapState将对象展开he:'sum、xuexiao:school、xueke:'subject'//借助mapState生成计算属性,从state中读取数据(数组写法)//...mapState(['sum' ,'school', 'subject']) //通过mapState生成名称为数组中对应的名称的方法//...mapGetters({bigsum:'bgsum'}),...mapGetters(['bigsum'])},methods:{
/* increment(){this.$store.dispatch('jia',this.n)},decreament(){this.$store.dispatch('jian', this.n)},*///借助mapMutations生成对应的方法,方法中会调用commit去联系mutation(对象写法)...mapMutations({increment:'JIA',decreament:'JIAN'}),//...mapMutations(['JIA','JIAN']),//使用数组的方式,但是template里对应的标签需要改为相同的名字//==============================================/*incramentOdd(){this.$store.dispatch('jiaOdd',this.n)},increamentWait(){this.$store.dispatch('jiaWait',this.n)},*/...mapActions({incramentOdd:'jiaOdd',increamentWait:'jiaWait'}),// ...mapActions(['jiaOdd','jiaWait'])},mounted() {console.log(this)}
}
</script><style scoped>
button{margin-right: 8px;
}
</style>
persons.vue代码如下:
<template><div><input type="text" placeholder="请输入名字" v-model="name"></input> //注意绑定双向绑定name,否则清空不了<button @click="AddPerson">点击添加</button><ul><li v-for="p in personsList" :key="p.id">{{p.name}}</li></ul><h1>上方的和为:{{sum}}</h1></div>
</template><script>import {mapState,mapMutations} from "vuex"
import {nanoid} from 'nanoid'
export default {name: "Persons",data(){return{name:''}},computed:{personsList(){return this.$store.state.persons},sum(){return this.$store.state.sum}},methods:{AddPerson(){const personObj = {name:this.name,id:nanoid()}this.$store.commit('AddPersons',personObj)this.name = ''}}
}
</script><style scoped></style>
index.js代码如下:
<template><div><input type="text" placeholder="请输入名字" v-model="name"></input> //注意绑定双向绑定name,否则清空不了<button @click="AddPerson">点击添加</button><ul><li v-for="p in personsList" :key="p.id">{{p.name}}</li></ul><h1>上方的和为:{{sum}}</h1></div>
</template><script>import {mapState,mapMutations} from "vuex"
import {nanoid} from 'nanoid'
export default {name: "Persons",data(){return{name:''}},computed:{personsList(){return this.$store.state.persons},sum(){return this.$store.state.sum}},methods:{AddPerson(){const personObj = {name:this.name,id:nanoid()}this.$store.commit('AddPersons',personObj)this.name = ''}}
}
</script><style scoped></style>
vuex模块化编码
index.js文件代码如下:
import Vue from 'vue';
import Vuex from 'vuex';
import nanoid from 'nanoid'
Vue.use(Vuex)
import Count from "./count"
import Persons from "./Persons";
//创建store
export default new Vuex.Store({modules:{ //以模块化注册Count: Count,Persons:Persons}
})
count.js文件代码如下:
//模块一,求和相关配置
export default {namespaced:true,actions:{jia(context,value){console.log('进入了jia')context.commit('JIA',value)},jian(context,value){context.commit('JIAN',value)},jiaOdd(context,value){if (context.state.sum%2){context.commit('JIA',value)}},jiaWait(context,value){setTimeout(()=>{context.commit('JIA',value)},1000)}},mutations:{JIA(state,value){console.log('进入了JIA')state.sum += value},JIAN(state,value){state.sum -= value},},state:{sum : 0,school:'武汉大学',subject:'Vue前端框架',},getters:{bigsum(state){return state.sum * 10}}
}
Persons.js文件代码如下:
import axios from "axios";
import {nanoid} from "nanoid";
//模块二,人员相关配置
export default {namespaced: true,actions: {addPersonWang(context,value){if (value.name.indexOf('王')==0){context.commit('AddPersons',value)}else {alert('请输入一个性王的人!')}},addPersonServer(context){axios.get("https://api.uixsj.cn/hitokoto/get?type=social").then(response =>{context.commit('AddPersons',{id:nanoid(),name:response.data})},err=>{alert(err.message)})}},mutations:{AddPersons(state,value){state.persons.unshift(value)}},state:{persons:[{name:'张三',id:1},{name: '李四', id:2},{name: '王五', id: 3}]},getters:{firstPersonName(state){return state.persons[0].name}}
}
Count.vue文件代码如下:
<template><div>
<!-- <h1>当前求和为:{{$store.state.sum}}</h1>-->
<!-- <h1>当前求和放大十倍为:{{$store.getters.bigsum}}</h1>-->
<!-- <h1>我在{{$store.state.school}}学习{{$store.state.subject}}</h1> --><h1>当前求和为:{{sum}}</h1><h2>列表的第一个人是{{firstPersonName}}</h2><h1>当前求和放大十倍为:{{bigsum}}</h1><h1>我在{{school}}学习{{subject}}</h1><h3>总人数时:{{persons.length}}</h3><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="increment(n)">+</button><button @click="decreament(n)">-</button><button @click="incramentOdd(n)">当前求和为奇数再加</button><button @click="increamentWait(n)">等等再加</button></div>
</template><script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex' //注意,导入时要加大括号export default {name: "Cout",data(){return {n:1}},computed:{...mapState('Count',['sum' ,'school', 'subject']), //从Count模块取出数据...mapState('Persons',['persons']), //从Persons模块取出数据...mapGetters('Count',['bigsum']),...mapGetters('Persons',['firstPersonName']),firstPersonName(){return this.$store.getters['Persons/firstPersonName']}},methods:{
/* increment(){this.$store.dispatch('jia',this.n)},decreament(){this.$store.dispatch('jian', this.n)},*///借助mapMutations生成对应的方法,方法中会调用commit去联系mutation(对象写法)...mapMutations({increment:'Count/JIA',decreament:'Count/JIAN'}),//...mapMutations(['JIA','JIAN']),//使用数组的方式,但是template里对应的标签需要改为相同的名字//==============================================/*incramentOdd(){this.$store.dispatch('jiaOdd',this.n)},increamentWait(){this.$store.dispatch('jiaWait',this.n)},*/...mapActions({incramentOdd:'Count/jiaOdd',increamentWait:'Count/jiaWait'}),// ...mapActions(['jiaOdd','jiaWait'])},mounted() {console.log(this)}
}
</script><style scoped>
button{margin-right: 8px;
}
</style>
Persons.vue文件代码如下:
<template><div>
<!-- //注意绑定双向绑定name,否则清空不了 --><input type="text" placeholder="请输入名字" v-model="name"></input><button @click="AddPerson">点击添加</button><button @click="addWang">添加一个性王的人</button><button @click="addPersonServer">添加一个人,名字随机</button><ul><li v-for="p in personsList" :key="p.id">{{p.name}}</li></ul><h1>上方的和为:{{sum}}</h1></div>
</template><script>import {mapState,mapMutations} from "vuex"
import {nanoid} from 'nanoid'
export default {name: "Persons",data(){return{name:''}},computed:{personsList(){return this.$store.state.Persons.persons},sum(){return this.$store.state.Count.sum}},methods:{AddPerson(){const personObj = {name:this.name,id:nanoid()}this.$store.commit('Persons/AddPersons',personObj)this.name = ''},addWang(){const personwang = {name:this.name,id: nanoid()}this.$store.dispatch('Persons/addPersonWang',personwang)this.name = ''},addPersonServer(){this.$store.dispatch('Persons/addPersonServer')}}
}
</script><style scoped></style>