【前端系列笔记007】Vue(三)第四章第五章
第四章:Vue中的ajax
4.1 解决开发环境中Ajax跨域问题
方法一
在vue.config.js中添加如下配置:
//开启代理服务器(方式一)
devServer:{
proxy:'http://localhost:5000'
}
js
说明:
- **优点:**配置简单,请求资源时直接发给前端(8080)即可
- **缺点:**不能配置多个代理,不能灵活地控制请求是否走代理
- **工作方式:**若按照上述配置代理,当请求了前端不存在的资源时,那么请求会转发给服务器(优先匹配前端资源)
方法二
编写vue.config.js配置具体代理规则:
//开启代理服务器(方式二)
devServer:{
proxy:{
'/student':{//匹配所有以'/student'开头的请求路径
target:"http://localhost:5000",//代理目标的基础路径
pathRewrite:{'^/student':''},
ws:true, //用于支持webSocket
changeOrigin:true //默认为true,用于控制请求头中的host值,值为true时,服务器收到的请求头中的host为:localhost:5001,值为true时,服务器收到的请求头中的host为:localhost:8080
},
'car':{//匹配所有以'/car'开头的请求路径
target: "http://localhost:5001",//代理目标的基础路径
pathRewrite:{'^/car':''},
ws:true, //用于支持webSocket
changeOrigin:true //默认为true,用于控制请求头中的host值,值为true时,服务器收到的请求头中的host为:localhost:5001,值为true时,服务器收到的请求头中的host为:localhost:8080
}
}
}
vue

说明:
- **优点:**可以配置多个代理,且可以灵活地控制请求是否走代理
- **缺点:**配置略显繁琐,请求资源时必须加前缀
4.2 github用户搜索案例
main.js
//引入Vue
import Vue from "vue";
//引入App
import App from "./App";
//关闭vue的生产提示
Vue.config.productionTip=false
//创建vm
new Vue({
el:"#root",
render:h=>h(App),
beforeCreate() {
Vue.prototype.$bus=this
}
})
js

App.vue
<template>
<div class="container">
<Search></Search>
<List></List>
</div>
</template>
<script>
// import 'assets/css/bootstrap.css'
import Search from "./components/Search";
import List from "./components/List";
export default {
name: "App",
components: {List, Search}
}
</script>
<style>
</style>
vue

List.vue
<template>
<div class="row">
<!-- 展示用户列表 -->
<div v-show="info.users.length" class="card" v-for="user in info.users" :key="user.id">
<a :href="user.html_url" target="_blank">
<img :src="user.avatar_url" style='width: 100px'/>
</a>
<p class="card-text">{{user.login}}</p>
</div>
<!-- 展示欢迎词 -->
<h1 v-show="info.isFirst">欢迎使用!</h1>
<!-- 展示加载中 -->
<h1 v-show="info.isLoading">加载中...</h1>
<!-- 展示错误信息 -->
<h1 v-show="info.errMsg">{{info.errMsg}}</h1>
</div>
</template>
<script>
export default {
name: "List",
data(){
return {
info:{
isFirst:true,
isLoading:false,
errMsg:"",
users:[]
}
}
},
mounted() {
this.$bus.$on('updateListData',(dataObj)=>{
console.log(dataObj)
this.info={...this.info,...dataObj}
})
},
beforeDestroy() {
this.$bus.$off('updateListData')
}
}
</script>
<style scoped>
.album {
min-height: 50rem; /* Can be removed; just added for demo purposes */
padding-top: 3rem;
padding-bottom: 3rem;
background-color: #f7f7f7;
}
.card {
float: left;
width: 33.333%;
padding: .75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card > img {
margin-bottom: .75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
</style>
vue

Search.vue
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Users</h3>
<div>
<input type="text" placeholder="enter the name you search" v-model="keyWord"/>
<button @click="searchUsers">Search</button>
</div>
</section>
</template>
<script>
import axios from 'axios'
export default {
name: "Search",
data(){
return{
keyWord:""
}
},
methods:{
searchUsers() {
//请求前更新list数据
this.$bus.$emit('updateListData',{
isFirst:false,
isLoading:true,
errMsg:'',
users:[]
})
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
response=>{
console.log('请求成功',response.data)
//请求成功后
this.$bus.$emit('updateListData',{
isLoading:false,
errMsg:'',
users:response.data.items
})
},
error=>{
console.log('请求失败了',error.message)
//请求失败后
this.$bus.$emit('updateListData',{
isLoading:false,
errMsg:error.message,
users:[]
})
}
)
}
}
}
</script>
<style scoped>
</style>
vue

4.3 插槽
**作用:**让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于:父组件=== >子组件
**分类:**默认插槽、具名插槽、作用域插槽
使用方式:
1.
默认插槽:
父组件中的:
<Category>
<div>html结构...</div>
</Category>
子组件中:
<template>
<div>
<!--定义插槽-->
<slot>插槽内容...</slot>
</div>
</template>
vue

具名插槽:
父组件中:
<Category>
<template slot="center">
<div>html结构1</div>
</template>
<template v-slot:footer>
<div>html结构2</div>
</template>
</Category>
子组件中:
<template>
<div>
<!--定义插槽-->
<slot name="center">插槽默认内容...</slot>
<slot name="footer">插槽默认内容...</slot>
</div>
</template>
vue

作用域插槽:
理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。 (games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
具体编码:
父组件中的:
<Category title="游戏">
<template scope="youxis">
<ul>
<li v-for="(item,index) in youxis.games" :key="index">{{item}}</li>
</ul>
</template>
</Category>
<Category title="游戏">
<template scope="youxis">
<ol>
<li v-for="(item,index) in youxis.games" :key="index">{{item}}</li>
</ol>
<h4>{{youxis.msg}}</h4>
</template>
</Category>
子组件中:
<template>
<div class="category">
<h3>{{title}}分类</h3>
<slot :games="games" :msg="msg">我是默认的内容</slot>
</div>
</template>
<script>
export default {
name: "Category",
props:['title'],
data() {
return {
games:['红色警戒','LOL','cf','超级玛丽'],
msg:"你好!"
}
}
}
</script>
vue

第五章:vuex
5.1 理解vuex
5.1.1 vuex是什么
- 概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的 共享状态进行集中式的管理(读写),也是一种组件间通信的方式,且适用于任意组件间通信
- Github地址:https://github.com/vuejs/vuex
5.1.2 什么时候使用Vuex
- 多个组件依赖于同一状态
- 来自不同组件的行为需要变更同一状态
5.1.3 Vuex工作原理图

5.2 搭建vuex环境
创建文件:src/store/index.js
//该文件用于创建vuex中最为核心的store
//引入Vuex
import Vuex from "vuex";
//引入vue核心库
import Vue from "vue";
//使用vuex插件
Vue.use(Vuex)
//准备actions---用于响应组件中的动作
const actions={}
//准备mutations---用于操作数据(state)
const mutations={}
//准备state---用于存储数据
const state={}
//创建并暴露store
export default new Vuex.Store({
actions:actions,
mutations,
state
})
js

在main.js中创建vm时传入store配置项
//引入Vue
import Vue from "vue";
//引入App
import App from "./App";
//引入store
import store from "./store";
//关闭vue的生产提示
Vue.config.productionTip=false
//创建vm
new Vue({
el:"#root",
render:h=>h(App),
store,
beforeCreate() {
Vue.prototype.$bus=this
}
})
js

5.3 基本使用
初始化数据,配置actions、mutations,操作文件store.js
index.js
//该文件用于创建vuex中最为核心的store
//引入Vuex
import Vuex from "vuex";
import Vue from "vue";
//使用vuex插件
Vue.use(Vuex)
//准备actions---用于响应组件中的动作
const actions={
/*add(context,value){
context.commit('ADD',value)
},
jian(context,value){
context.commit('JIAN',value)
},*/
jiaOdd(context,value){
if (context.state.sum%2){
context.commit('ADD',value)
}
}
}
//准备mutations---用于操作数据(state)
const mutations={
ADD(state,value){
state.sum+=value
},
JIAN(state,value){
state.sum-=value
}
}
//准备state---用于存储数据
const state={
sum:0,//当前的和
}
//创建并暴露store
export default new Vuex.Store({
actions:actions,
mutations,
state
})
js

组件中读取vuex中的数据:$store.state.sum
组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据)或$store.commit('mutations中的方法名',数据)
**备注:**若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit
在组件中的使用方法:
Count.vue
<template>
<div>
<h1>当前求和为:{{$store.state.sum}}</h1>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前求和为奇数再加</button>
<button @click="incrementWait">等一等再加</button>
</div>
</template>
<script>
export default {
name: "Count",
data() {
return {
n:1,//用户选择的数字
}
},
methods:{
increment(){
//this.$store.dispatch('add',this.n)
this.$store.commit('ADD',this.n)
},
decrement(){
//this.$store.dispatch('jian',this.n)
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
setTimeout(()=>{
this.$store.dispatch('add',this.n)
},1000)
}
},
mounted() {
}
}
</script>
<style scoped>
</style>
vue

5.4 getters的使用
**概念:**当state中的数据需要进行加工后再使用时,可以使用getters加工
在store.js中追加getters配置:
//准备getters——用于将state中的数据进行加工
const getters={
bugSum(state){
return state.sum*10
}
}
//创建并暴露store
export default new Vuex.Store({
actions:actions,
mutations,
state,
getters
})
js

组件中读取数据: $store.getters.bigSum
<h1>当前求和放大10倍后为:{{$store.getters.bugSum}}</h1>
vue
5.5 四个map方法的使用
mapState
**mapState方法:**用于帮助我们映射state中的数据作为计算属性
computed:{
//借助mapState生成计算属性,从state中读取数据(对象写法)
...mapState({sum:"sum",school:"school",subject:"subject"}),
//借助mapState生成计算属性,从state中读取数据(数组写法)
...mapState(['sum','school','subject']),
}
vue
mapGetters
**mapGetters方法:**用于帮助我们映射getters中的数据作为计算属性
computed:{
//借助mapGetters生成计算属性,从getters中读取数据(对象写法)
...mapGetters({bigSum:'bigSum'})
//借助mapGetters生成计算属性,从getters中读取数据(数组写法)
...mapGetters(['bigSum'])
}
vue
mapActions
**mapActions方法:**用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数
//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
...mapActions({incrementOdd:'jiaOdd',incrementWait:"incrementWait"}),
//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
...mapActions(['incrementOdd','incrementWait']),
vue
mapMutations
**mapMutations方法:**用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
...mapMutations({increment:'ADD',decrement:'JIAN'}),
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)
...mapMutations(['increment','decrement']),
vue
5.6 模块化+命名空间
**目的:**让代码更好维护,让多种数据分类更加明确
修改store.js:
//人员管理功能相关的配置
const personOptions={
namespaced: true,//开启命名空间,默认关闭
actions: {...},
mutations:{...},
state:{x:1...},
getters:{
firstPersonName(state){
return state.personList[0].name
}
}
}
const countOptions= {
namespaced:true,//开启命名空间,默认关闭
actions:{...},
mutations:{...},
state:{
sum:0,
},
getters:{
bigSum(state){
return state.sum*10
}
}
}
//创建并暴露store
export default new Vuex.Store({
modules:{
countOptions,
personOptions
}
})
js

开启命名空间后,组件中读取state数据:
//方式一:自己直接读取
this.$store.state.personOptions.personList
//方式二:借助mapState读取
...mapState('countOptions',['sum','school','subject'])
vue
开启命名空间后,组件中读取getters数据:
//方式一:自己直接读取
this.$store.getters["personOptions/firstPersonName"]
//方式二:借助mapGetters读取
...mapGetters('countOptions',['bigSum'])
vue
开启命名空间后,组件中调用dispatch:
//方式一:自己直接dispatch
this.$store.dispatch('personOptions/addPersonWang',person)
//方式二:借助mapActions读取
...mapActions('countOptions',{incrementOdd:'jiaOdd',incrementWait:"incrementWait"})
vue
开启命名空间后,组件中调用commit:
//方式一:自己直接commit
this.$store.commit('personOptions/ADD_PERSON',person)
//方式二:借助mapMutations读取
...mapMutations('countOptions',{increment:'ADD',decrement:'JIAN'}),
vue
