个人技术分享

Ajax库-axios

安装axios:npm i axios

请求发出后,报错:请求跨域

在这里插入图片描述

解决方式

解决方式1:使用代理服务器:在vue.config.js中添加如下配置
```html
devServer:{
  proxy:"http://ip:端口"
}
```
代码示例
  • vue.config.js添加后台服务路径
    	module.exports={
    	  devServer:{
    	    proxy:'http://localhost:9006'
    	  }
    	} 
    
  • 组件
<template>
  <div id="app">
	  <input type="search" v-model="key"/>
	  <button @click="getStudentInfo">获取学生信息</button>
	  <hr/>
	  <table>
		  <tr>
			  <td>ID</td>
			  <td>学生账号</td>
			  <td>学生姓名</td>
			  <td>学生年龄</td>
			  <td>学生性别</td>
			  <td>所属老师</td>
		  </tr>
		  <tr v-for="(student,index) in studentList" :key="student.id">
			  <td>{{student.id}}</td>
			  <td>{{student.stuCode}}</td>
			  <td>{{student.stuName}}</td>
			  <td>{{student.stuAge}}</td>
			  <td>{{student.stuGender}}</td>
			  <td>{{student.teName}}</td>
		  </tr>
	  </table>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  name: 'app',
  components: {
  },
  data(){
	  return{
		  studentList:[],
		  key: ''
	  }
  },
  methods:{
	  getStudentInfo(){
		  //   axios.get('http://localhost:8080/student/getStudentInfo').then(
		  axios.post(`http://localhost:8080/school/student/getStudentInfo?key=${this.key}`).then(
			response=>{
				console.log("请求成功!",response.data)
				this.studentList = response.data
			},
			error=>{
				console.log("请求失败",error.message)
			}
		  )
	  },
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
table{
	margin: auto;
	border: 1px solid black;
	border-spacing: 0;
}
td{
	width: 80px;
	border: 1px solid black;
}
tr{
	height: 50px;
}
</style>
优点
  • 配置简单,请求资源时直接发给前端(8080)即可。
缺点
  • 不能配置多个代理,不能灵活的控制请求是否走代理。
工作方式
  • 若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)
解决方式2:编写vue.config.js配置具体代理规则
  • 编写vue.config.js配置具体代理规则
    proxy: {
          '/api1': {// 匹配所有以 '/api1'开头的请求路径
            target: 'http://localhost:9006',// 代理目标的基础路径
            changeOrigin: true,// 用于控制请求头中的host值
            pathRewrite: {'^/api1': ''}
     }
    
  • changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
  • changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
  • changeOrigin默认值为true
优点
  • 可以配置多个代理,且可以灵活的控制请求是否走代理
缺点
  • 配置略微繁琐,请求资源时必须加前缀
代码示例

vue.config.js添加后台服务路径

module.exports = {
	devServer: {
      proxy: {
      '/school': {// 匹配所有以 '/api1'开头的请求路径
        target: 'http://localhost:9006',// 代理目标的基础路径
        changeOrigin: true,// 用于控制请求头中的host值
		//匹配所有以school开头的请求路径,将school替换为空字符串
		//可以将下面一行注释掉看看效果
        pathRewrite: {'^/school': ''}
      },
      '/api2': {// 匹配所有以 '/api2'开头的请求路径
        target: 'http://localhost:9007',// 代理目标的基础路径
        changeOrigin: true,// 用于控制请求头中的host值
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}
  • 组件代码不变,然后继续访问
解决方式3:如果是springboot项目的话,只需要在对应的controller层加上@CrossOrigin注解

Ajax库-vue-resource

  • vue 插件库, vue1.x 使用广泛,官方已不维护。交给别的团队维护了,因此不推荐使用该方式。
  • 安装vue-resource:npm i vue-resource
  • 引用:
    //引入插件
    import vueResource from 'vue-resource'
    
    //使用插件,这样vm和vc身上都会有$http
    Vue.use(vueResource)
    
  • 具体使用方式和axios区别就是把axios.get改成this.$http.get,其他都一样
    在这里插入图片描述

slot 插槽

作用:

  • 让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件

理解:

  • 父组件向子组件传递带数据的标签,当一个组件有不确定的结构时, 就需要使用slot 技术
  • 注意:插槽内容是在父组件中编译后, 再传递给子组件的

分类:

  • 默认插槽
  • 具名插槽
  • 作用域插槽
    在这里插入图片描述

默认插槽

  • 插槽中的元素是在父组件完成解析之后塞到子组件的,所以样式写在父组件或子组件都行,如果写在父组件会把样式带好传过去,如果写在子组件样式也能控制

  • 父组件:

          <Category>
             <html结构>xxxx</html结构>
          </Category>
    
  • 子组件:

             <template>
                 <div>
    	        <!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
    	        <slot>我是一些默认值,当使用者没有传递具体结构时,我会出现</slot>
                 </div>
             </template>
    
代码示例
父组件
<template>
    <div id="app">
        <!-- <Category title="阵营分类" :list="aroundList"></Category>
        <Category title="角色分类" :list="roleList"></Category>
        <Category title="位置分类" :list="addressList"></Category> -->

        <!-- 默认插槽 -->
        <div id="category1">
            <Category title="阵营分类">
                <ul>
                    <li v-for="(aStr,index) in aroundList" :key="index">{{aStr}}</li>
                </ul>
                <img src="./assets/1.webp" alt="卡莎"/>
            </Category>
            <Category title="角色分类" :list="roleList">
                <ul>
                    <li v-for="(rStr,index) in roleList" :key="index">{{rStr}}</li>
                </ul>
                <video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
            </Category>
            <Category title="位置分类" :list="addressList">

            </Category>
        </div>
        <hr/>
    </div>
</template>

<script>
import Category from './components/Category.vue'
export default {
    name: 'app',
    components: {
        Category
    },
    data(){
        return{
            aroundList:['德玛西亚','艾欧尼亚','影流','恕瑞玛','均衡教派'],
            roleList:['战士','法师','坦克','射手','刺客'],
            addressList:['上单','打野','中单','ADC','辅助']

        }
    }
}
</script>

<style>
#category1,#category2,#category3,.baidu {
    display: flex;
    justify-content: space-around;
}
img,video{
    width: 100%;
}
</style>
子组件
<template>
	<div id="category">
		<h3>{{title}}</h3>
		<!-- 定义一个插槽,父组件使用<Category><标签></标签></Category>时,
			会将<标签></标签>传到这里 -->
		<slot>默认显示一些值,若没有传递具体结果过来,则显示这些内容</slot>
		<!-- <ul>
			<li v-for="(item,index) in list" :key="index">
				{{item}}
			</li>
		</ul> -->
	</div>
</template>

<script>
	export default{
		// eslint-disable-next-line vue/multi-word-component-names
		name:'Category',
		props:['title'],
		data(){
			return{
				
			}
		}
	}
</script>

<style scoped>
	#category{
		background-color: orange;
		width: 200px;
		height: 300px;
	}
	h3{
		text-align: center;
		background-color: skyblue;
	}
</style>

具名插槽

  • vue2.6新提出了一个 slot="center"写法 ,且新写法: v-slot:footer ,但只能在 template 用

  • 父组件:

           <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>
    
代码示例
父组件
<template>
    <div id="app">
        <!-- <Category title="阵营分类" :list="aroundList"></Category>
        <Category title="角色分类" :list="roleList"></Category>
        <Category title="位置分类" :list="addressList"></Category> -->
        <div id="category2">
            <Category2 title="阵营分类">
                <ul slot="liValue">
                    <li v-for="(aStr2,index2) in aroundList" :key="index2">{{aStr2}}</li>
                </ul>
                <img slot="staticFile" src="./assets/1.webp" alt="卡莎"/>
            </Category2>
            <Category2 title="角色分类" :list="roleList">
                <video slot="liValue" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
                <!-- <template slot="staticFile"> -->
                <template v-slot:staticFile>
                    <div class="baidu">
                        <a slot="staticFile" href="www.baidu.com">百度一下</a>
                        <a slot="staticFile" href="www.baidu.com">百度两下</a>
                    </div>
                    <h4>百度三下</h4>
                </template>
            </Category2>
            <Category2 title="位置分类" :list="addressList">

            </Category2>
        </div>
        <hr/>
    </div>
</template>

<script>
import Category2 from './components/Category2.vue'
export default {
    name: 'app',
    components: {
        Category2
    },
    data(){
        return{
            aroundList:['德玛西亚','艾欧尼亚','影流','恕瑞玛','均衡教派'],
            roleList:['战士','法师','坦克','射手','刺客'],
            addressList:['上单','打野','中单','ADC','辅助']

        }
    }
}
</script>

<style>
#category1,#category2,#category3,.baidu {
    display: flex;
    justify-content: space-around;
}
img,video{
    width: 100%;
}
</style>

子组件
<template>
	<div id="category">
		<h3>{{title}}</h3>
		<!-- 定义一个插槽,父组件使用<Category><标签></标签></Category>时,
			会将<标签></标签>传到这里 -->
		<slot name="liValue">liValue:默认显示一些值,若没有传递具体结果过来,则显示这些内容</slot>
		<slot name="staticFile">staticFile:默认显示一些值,若没有传递具体结果过来,则显示这些内容</slot>
	</div>
</template>

<script>
	export default{
		// eslint-disable-next-line vue/multi-word-component-names
		name:'Category2',
		props:['title'],
		data(){
			return{
				
			}
		}
	}
</script>

<style scoped>
	#category{
		background-color: orange;
		width: 200px;
		height: 320px;
	}
	h3{
		text-align: center;
		background-color: skyblue;
	}
</style>

作用域插槽

  • 数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定

  • games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定

  • 父组件:

           <Category>
                <template scope="list">
    		<div>{{list.xx}}</div>
    	    </template>
            </Category>
    
  • 子组件:

           <template>
                <div>
                   <!-- 定义插槽 -->
                   <slot :xx="xxxx" :yy="yyyy" zz="zzzz">插槽默认内容...</slot>
                </div>
            </template>
    
代码示例
父组件
<template>
    <div id="app">
        <!-- <Category title="阵营分类" :list="aroundList"></Category>
        <Category title="角色分类" :list="roleList"></Category>
        <Category title="位置分类" :list="addressList"></Category> -->

        <div id="category3">
            <Category3 title="阵营分类">
                <template scope="list">
                    <ul>
                        <li v-for="(aStr3,index3) in list.aroundList3" :key="index3">{{aStr3}}</li>
                    </ul>
                    <img src="./assets/1.webp" alt="卡莎"/>
                </template>
            </Category3>
            <Category3 title="角色分类">
                <template scope="list">
                    <ul>
                        <li v-for="(rStr3,index3) in list.roleList3" :key="index3">{{rStr3}}</li>
                    </ul>
                    <video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
                </template>
            </Category3>
            <Category3 title="位置分类">
            </Category3>
            <Category3 title="百度一下">
                <template scope="list">
                    <h4>{{list.baidu}}</h4>
                </template>
            </Category3>
        </div>
    </div>
</template>

<script>
import Category3 from './components/Category3.vue'
export default {
    name: 'app',
    components: {
        Category3
    },
    data(){
        return{
            aroundList:['德玛西亚','艾欧尼亚','影流','恕瑞玛','均衡教派'],
            roleList:['战士','法师','坦克','射手','刺客'],
            addressList:['上单','打野','中单','ADC','辅助']

        }
    }
}
</script>

<style>
#category1,#category2,#category3,.baidu {
    display: flex;
    justify-content: space-around;
}
img,video{
    width: 100%;
}
</style>
子组件
<template>
	<div id="category">
		<h3>{{title}}</h3>
		<!-- 定义一个插槽,父组件使用<Category><标签></标签></Category>时,
			会将<标签></标签>传到这里 -->
		<slot 
			:aroundList3="aroundList" 
			:roleList3="roleList" 
			:addressList3="addressList"
			baidu="百度一下"
		>
				默认显示一些值,若没有传递具体结果过来,则显示这些内容
		</slot>
	</div>
</template>

<script>
	export default{
		name:'Category',
		props:['title'],
		data(){
			  return{
				  aroundList:['德玛西亚','艾欧尼亚','影流','恕瑞玛','均衡教派'],
				  roleList:['战士','法师','坦克','射手','刺客'],
				  addressList:['上单','打野','中单','ADC','辅助']
				  
			  }
		}
	}
</script>

<style scoped>
	#category{
		background-color: orange;
		width: 200px;
		height: 300px;
	}
	h3{
		text-align: center;
		background-color: skyblue;
	}
</style>

vuex

概念:

  • 专门在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 vue 应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
  • Github 地址: https://github.com/vuejs/vuex

什么时候使用 Vuex:

  • 多个组件依赖于同一状态
  • 来自不同组件的行为需要变更同一状态

Vuex原理图

actions、mutations、state都是由store管理的
在这里插入图片描述

使用Vuex

  • 安装:npm i vuex
  • 引入:在src下创建store目录,在该目录下创建index.js,然后加入Vue.use(Vuex),在main.js中添加import store from './store'
  • 弄出来store
  • 让所有vc都能看到store

基本使用

  • 初始化数据、配置actions、mutations、state
  • actions中的方法命名规范:方法名小写驼峰(context,value),第一个参数context上下文,可以拿到commit、state等,第二个是传过来的值
  • mutations中的方法命名规范:方法名大写(state,value)
  • 组件中读取vuex中的数据:$store.state.xx
  • 组件中修改vuex中的数据:$store.dispatch(‘action中的方法名’,数据)或 $store.commit(‘mutations中的方法名’,数据)

代码示例

src/store/index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
	/* jia(context,value){
		console.log('actions中的jia被调用了')
		context.commit('JIA',value)
	},
	jian(context,value){
		console.log('actions中的jian被调用了')
		context.commit('JIAN',value)
	}, */
	jiaOdd(context,value){
		console.log('actions中的jiaOdd被调用了')
		if(context.state.sum % 2){
			context.commit('JIA',value)
		}
	},
	jiaWait(context,value){
		console.log('actions中的jiaWait被调用了')
		setTimeout(()=>{
			context.commit('JIA',value)
		},500)
	}
}
//准备mutations——用于操作数据(state)
const mutations = {
	JIA(state,value){
		console.log('mutations中的JIA被调用了')
		state.sum += value
	},
	JIAN(state,value){
		console.log('mutations中的JIAN被调用了')
		state.sum -= value
	}
}
//准备state——用于存储数据
const state = {
	sum:0 //当前的和
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})

子组件

<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>
		</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.commit('JIA',this.n)
			},
			decrement(){
				this.$store.commit('JIAN',this.n)
			}, */
			/* incrementOdd(){
				this.$store.dispatch('jiaOdd',this.n)
			},
			incrementWait(){
				this.$store.dispatch('jiaWait',this.n)
			}, */
		},
		mounted() {
			console.log('Count',this)
		},
	}
</script>

<style lang="css">
	button{
		margin-left: 5px;
	}
</style>

main.js:引入store

//引入store
import store from './store'

父组件

<template>
  <div id="app">
	  <Count></Count>
	  <!-- <button @click="demo">点击</button>
	  <h1>{{count}}</h1> -->
  </div>
</template>

<script>
import Count from './components/Count.vue'

export default {
  name: 'app',
  components: {
    Count
  },
  data() {
  	return{
			count:0
	}
  },
  methods:{
	  
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
  • 备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit