Vue2-脚手架配置代理(同源策略及跨域问题)、github获取用户案例、vue-resource、插槽

news/2024/7/10 1:30:59 标签: github, vue.js, 前端, javascript, es6, vue

🥔:勿失心所念,万事尽可期

更多Vue知识请点击——Vue.js

VUE2-Day10

    • 脚手架配置代理
      • 1、引出跨域问题
      • 2、配置代理服务器
        • (1)方式一
        • (2)方式二
    • github案例
    • vue-resource
    • 插槽
      • 1、默认插槽
      • 2、具名插槽
      • 3、作用域插槽

脚手架配置代理

先在脚手架文件目录下npm i axios安装一下axios

忘记如何用axios发请求的点击此处复习

1、引出跨域问题

这里有一个url为http://localhost:5000的服务器,此时url为http://localhost:8080前端应用要请求这个服务器的数据,由于同源策略,会发生跨域。

我们之前已经了解过同源策略、跨域问题及解决方法点击此处复习

跨域就是违反同源策略,同源策略就是协议、域名、端口号三个必须完全一样
解决跨域请求数据问题,要么让后端加上那个Access-Control-Allow-Origin’, ‘*’,要么用jsonp的script的src属性,但这两种用的不多,我们还有第三种方式,那就是借助一个代理服务器,其端口号和请求端口号一致(这里以8080举例)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TBC0UwfR-1692525445103)(D:\wxf\前端学习笔记\vue2+vue3\笔记图片\跨域问题.png)]

那么上面的问题我们可以这样解决:

可以利用vue-cli配置一个中间的代理服务器,其url也是http://localhost:8080(vue项目服务器和代理服务器是一台服务器8080),代理服务器8080和5000服务器之间交换数据不需要遵循同源策略(服务器和服务器之间互相访问用http即可),所以可以8080服务器可以把8080前端应用的请求转发给5000端口服务器

2、配置代理服务器

(1)方式一

  • vue.config.js中添加如下配置开启代理服务器
javascript">//开启代理服务器
  devServer: {
    proxy: 'http://localhost:5000',
  },
  • 在App.vue中使用代理服务器
javascript"><template>
  <div>
    <button @click="getStudents">获取学生信息</button>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  name: 'App',
  methods: {
    getStudents() {
      axios.get('http://localhost:8080/students').then(
        (response) => {
          console.log('请求成功', response.data)
        },
        (error) => {
          console.log('请求失败', error.message)
        }
      )
    },
  },
}
</script>
  • 说明:
  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。

  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。

  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)。这话的意思就是说,如果8080本身就有students这个路径(比如我在脚手架文件的public里新建了个students),那么请求会先找8080的这个students,如果8080没有students,才会把请求转发给5000端口去拿5000的students。

  4. 注意:仔细观察8080和5000分别写在什么位置

(2)方式二

  • vue.config.js中添加如下配置开启两个代理服务器
javascript">//开启代理服务器(方式二)
  devServer: {
    //方式二可以加路径前缀,如果看到前缀就去请求5000,不会再从8080找数据
    proxy: {
      //前缀名字为potato
      '/potato': {
        //告诉ajax请求要转发给谁 
        target: 'http://localhost:5000',
        //pathRewrite把请求转发给5000时去掉potato路径
        //一般来说后端都会写成api/xxx,就不用手pathRewrite了
        pathRewrite: { '^/potato': '' },
        ws: true,  //用于支持websocket,不写默认为true
        //changeOrigin用于控制请求头中的host值
        // true就是把请求源改成和目标服务器一致(5000),false就是8080
        changeOrigin: true,  //写true比较合适,默认也是true(React里默认false)
      },
      '/demo': {
        target: 'http://localhost:5001',
        pathRewrite: { '^/demo': '' },
      },
    },
  • 在App.vue中使用代理服务器
javascript"><template>
  <div>
    <button @click="getStudents">获取学生信息</button>
    <button @click="getCars">获取汽车信息</button>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  name: 'App',
  methods: {
    getStudents() {
      axios.get('http://localhost:8080/potato/students').then(
        (response) => {
          console.log('请求成功', response.data)
        },
        (error) => {
          console.log('请求失败', error.message)
        }
      )
    },
    getCars() {
      axios.get('http://localhost:8080/demo/cars').then(
        (response) => {
          console.log('请求成功', response.data)
        },
        (error) => {
          console.log('请求失败', error.message)
        }
      )
    },
  },
}
</script>
  • 说明:
  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。

  2. 缺点:配置略微繁琐,请求资源时必须加前缀。

  3. 如果8080里有potato/students,那么还是会找8080里的文件,如果没有就发送给5000,不过一般来说是没有的,所以就发给5000然后再pathRewrite把potato去掉就行

github_153">github案例

https://api.github.com/search/users?q=xxx请求数据过来,然后点击搜索按钮可以显示所有github用户,点击这些用户头像还能进到他们的github个人页面.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PfXjMgGH-1692525445105)(D:\wxf\前端学习笔记\vue2+vue3\笔记图片\github案例.png)]

1、首先拆分html和css,这块儿直接用现成的,需要注意的是bootstrap样式需要在public下新建css文件夹粘贴bootstrap.css,然后去index.html引入,直接import会有问题
2、使用全局事件总线把请求的数据给List并使用v-for展示到页面
3、这里如果再完善一点,一上来显示欢迎词,发请求前显示loading,请求发送完若成功显示数据,失败则显示失败信息。这样的话在传数据时就要在不同的事件节点去触发全局事件并且传不同的值,比较好的做法是数据配置到对象里,传值也传一个对象,这样写起来比较方便。各个文件如下:

vue"><template>
  <div class="container">
    <Search />
    <List />
  </div>
</template>

<script>
import Search from './components/Search.vue'
import List from './components/List.vue'
export default {
  name: 'App',
  components: { Search, List },
}
</script>
  • 搜索部分Search.vue
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"
      />&nbsp;
      <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('请求成功')
          this.$bus.$emit('updateListData', {
            isFirst: false,
            isLoading: false,
            errMsg: '',
            users: response.data.items,
          })
        },
        (error) => {
          console.log('请求失败', error.message)
          this.$bus.$emit('updateListData', {
            isFirst: false,
            isLoading: false,
            errMsg: error.message,
            users: [],
          })
        }
      )
    },
  },
}
</script>
  • 显示数据部分List.vue
vue"><template>
  <div class="row">
    <!-- 展示用户列表 -->
    <div
      v-show="info.users.length"
      class="card"
      v-for="user in info.users"
      :key="user.login"
    >
      <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">欢迎来到Github!</h1>
    <!-- 展示加载中 -->
    <h1 v-show="info.isLoading">加载中,Loading......</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('我是List组件,收到数据:', users)
      //   可以一个一个传,但是麻烦
      //   this.isFirst = isFirst
      //   this.isLoading = isLoading
      //   this.errMsg = errMsg
      //   this.users = users
      this.info = { ...this.info, ...dataObj }
      console.log(dataObj)
    })
  },
}
</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: 0.75rem;
  margin-bottom: 2rem;
  border: 1px solid #efefef;
  text-align: center;
}

.card > img {
  margin-bottom: 0.75rem;
  border-radius: 100px;
}

.card-text {
  font-size: 85%;
}
</style>

vueresource_326">vue-resource

vue1.0时这个用的比较多,但是现在用axios比较多了,这个了解下就行,和axios很像,就把axios.get换成this.$http.get,其他的都一样
安装vue-resource :npm i vue-resource
引入插件:import vueResource from 'vue-resource
使用插件:Vue.use(vueResource)

使用:

javascript">this.$http.get('http://localhost:8081/api2/cars').then(
     response => {
     console.log('请求成功了',response.data)
     },
     error => {
     console.log('请求失败了',error.message)
     }

插槽

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

分类:默认插槽、具名插槽、作用域插槽

1、默认插槽

比如有那么一天,我们要在页面显示三个类别,每个类别下面有不同的文字,本来是我们把数据传给子组件然后使用v-for遍历生成的文字信息,但是产品经理突然让你把美食类的下面换成图片,电影类下面换成视频,怎么搞?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uD5jV5cd-1692525445106)(D:\wxf\前端学习笔记\vue2+vue3\笔记图片\默认插槽.png)]

有个非常好用的方法就是插槽,也就是使用slot标签在子组件挖个坑,然后在父组件的vc标签里面写东西往里边填

  • 子组件Category.vue
vue"><template>
  <div class="category">
    <h3>{{ title }}分类</h3>
    <!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'Category',
  props: ['title'],
}
</script>

<style>
.category {
  background-color: pink;
  width: 200px;
  height: 300px;
}
h3 {
  text-align: center;
  background-color: skyblue;
}
</style>
  • 父组件App.vue
vue"><template>
  <div class="container">
    <Category title="美食">
      <!--往slot插入东西-->
      <img src="http://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="" />
    </Category>
    <Category title="游戏">
      <!--往slot插入东西-->
      <li v-for="(game, index) in games" :key="index">
        {{ game }}
      </li>
    </Category>
    <Category title="电影">
      <!--往slot插入东西-->
      <video
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck.bunny.mp4"
      ></video>
    </Category>
  </div>
</template>

<script>
import Category from './components/Category.vue'
export default {
  name: 'App',
  components: { Category },
  data() {
    return {
      // foods: ['火锅', '烧烤', '小龙虾', '牛排'],
      games: ['战神4', '极品飞车', '鬼泣', '超级玛丽'],
      // films: ['《教父》', '《复仇者联盟》', '《绿皮书》', '《阿甘》'],
    }
  },
}
</script>

<style lang="css">
.container {
  display: flex;
  justify-content: space-around;
}
video {
  width: 100%;
}
img {
  width: 100%;
}
</style>

2、具名插槽

子组件使用name属性起个名,父组件理使用slot="名字"找到对应的坑位

  父组件中:
	  <template>
	  	<div>
	          <Category>
	              <div slot="center">中间的结构</div>
	              <a slot="center" href="http://www.zzy.com">中间的结构</a>
	  
	              <template v-slot:footer>  最新写法,要配合template使用
	                 <div>底部的结构</div>
	                 <h4>欢迎你</h4>
	              </template>
	          </Category>
	    </div>
	 </template>
 
  子组件中:
        <template>
            <div>
               <!-- 定义插槽 -->
               <slot name="center">插槽默认内容...</slot>
               <slot name="footer">插槽默认内容...</slot>
            </div>
        </template>
  • 子组件Category.vue
vue"><template>
  <div class="category">
    <h3>{{ title }}分类</h3>
    <!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
    <slot name="center"
      >我是一些默认值,当使用者没有传递具体结构时,我会出现1</slot
    >
    <slot name="footer"
      >我是一些默认值,当使用者没有传递具体结构时,我会出现2</slot
    >
  </div>
</template>

<script>
export default {
  name: 'Category',
  props: ['title'],
}
</script>

<style>
.category {
  background-color: pink;
  width: 200px;
  height: 300px;
}
h3 {
  text-align: center;
  background-color: skyblue;
}
</style>
  • 父组件App.vue
vue"><template>
  <div class="container">
    <Category title="美食">
      <!--往slot插入东西-->
      <img
        slot="center"
        src="http://s3.ax1x.com/2021/01/16/srJlq0.jpg"
        alt=""
      />
      <a slot="footer" href="https://blog.csdn.net/weixin_56498069?type=blog"
        >更多美食</a
      >
    </Category>
    <Category title="游戏">
      <!--往slot插入东西-->
      <ul slot="center">
        <li v-for="(game, index) in games" :key="index">
          {{ game }}
        </li>
      </ul>
      <template slot="footer">
        <div class="games">
          <a href="https://blog.csdn.net/weixin_56498069?type=blog">单机游戏</a>
          <a href="https://blog.csdn.net/weixin_56498069?type=blog">网络游戏</a>
        </div>
      </template>
    </Category>
    <Category title="电影">
      <!--往slot插入东西-->
      <video
        slot="center"
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck.bunny.mp4"
      ></video>
      <template v-slot:footer>
        <div class="files">
          <a href="https://blog.csdn.net/weixin_56498069?type=blog">经典</a>
          <a href="https://blog.csdn.net/weixin_56498069?type=blog">热门</a>
          <a href="https://blog.csdn.net/weixin_56498069?type=blog">推荐</a>
        </div>
        <h4>欢迎前来观影</h4>
      </template>
    </Category>
  </div>
</template>

<script>
import Category from './components/Category.vue'
export default {
  name: 'App',
  components: { Category },
  data() {
    return {
      // foods: ['火锅', '烧烤', '小龙虾', '牛排'],
      games: ['战神4', '极品飞车', '鬼泣', '超级玛丽'],
      // films: ['《教父》', '《复仇者联盟》', '《绿皮书》', '《阿甘》'],
    }
  },
}
</script>

<style lang="css">
.container,
.games,
.files {
  display: flex;
  justify-content: space-around;
}
video {
  width: 100%;
}
img {
  width: 100%;
}
h4 {
  text-align: center;
}
</style>

3、作用域插槽

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

有一天,产品经理让你把每个部分的数据换个形式,比如有序、无序、h

4标签,就像换成下边这样,咋整?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WJr0fPMK-1692525445107)(D:\wxf\前端学习笔记\vue2+vue3\笔记图片\作用域插槽.png)]

这里就用到了作用域插槽,如果数据不在App中了,而在Category.vue中,然后App.vue要用到数据,这时我们就可以在Category.vue中使用slot标签给父组件App传值,写法很像当时父给子传值的props写法,在标签里搞个:games=“games”,然后用到插槽的地方必须使用template标签包裹,并且配置scope属性来接收数据,接过来的是一个对象。

  • 子组件Category.vue
vue"><template>
  <div class="category">
    <h3>{{ title }}分类</h3>
    <!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
    <slot :games="games"
      >我是一些默认值,当使用者没有传递具体结构时,我会出现</slot
    >
  </div>
</template>

<script>
export default {
  name: 'Category',
  props: ['title'],
  data() {
    return {
      // foods: ['火锅', '烧烤', '小龙虾', '牛排'],
      games: ['战神4', '极品飞车', '鬼泣', '超级玛丽'],
      // films: ['《教父》', '《复仇者联盟》', '《绿皮书》', '《阿甘》'],
    }
  },
}
</script>

<style>
.category {
  background-color: pink;
  width: 200px;
  height: 300px;
}
h3 {
  text-align: center;
  background-color: skyblue;
}
</style>
  • 父组件App.vue
vue"><template>
  <div class="container">
    <Category title="游戏">
      <!--往slot插入东西-->
      <template scope="potato">
        <ul>
          <li v-for="(game, index) in potato.games" :key="index">
            {{ game }}
          </li>
        </ul>
      </template>
    </Category>
    <Category title="游戏">
      <!--往slot插入东西-->
      <template scope="potato">
        <ol>
          <li v-for="(game, index) in potato.games" :key="index">
            {{ game }}
          </li>
        </ol>
      </template>
    </Category>
    <Category title="游戏">
      <!--往slot插入东西-->
      <template scope="potato">
        <h4 v-for="(game, index) in potato.games" :key="index">
          {{ game }}
        </h4>
      </template>
    </Category>
  </div>
</template>

<script>
import Category from './components/Category.vue'
export default {
  name: 'App',
  components: { Category },
}
</script>

<style lang="css">
.container,
.games,
.files {
  display: flex;
  justify-content: space-around;
}
video {
  width: 100%;
}
img {
  width: 100%;
}
h4 {
  text-align: center;
}
</style>

s" :key=“index”>
{{ game }}








{{ game }}





http://www.niftyadmin.cn/n/4954869.html

相关文章

webpack 打包全流程

目录 1 webpack的安装 2 webpack的配置 配置流程&#xff1a; 1 webpack安装 2 创建webpack配置文件 webpack.config.js 3 配置入口 entry 单入口和多入口 2. 动态配置入口文件 4 配置出口 output 5 配置模式 mode&#xff08;webpack4&#xff09; 6 配置解析策略 …

嵌入式:ARM Day6

作业:完成cortex-A7核UART总线实验 目的&#xff1a;1.输入a,显示b&#xff0c;将输入的字符的ASCII码下一位字符输出 2.原样输出输入的字符串 源码&#xff1a; uart4.h #ifndef __UART4_H__ #define __UART4_H__#include "stm32mp1xx_rcc.h" #incl…

2023国赛数学建模E题思路模型代码 高教社杯

本次比赛我们将会全程更新思路模型及代码&#xff0c;大家查看文末名片获取 之前国赛相关的资料和助攻可以查看 2022数学建模国赛C题思路分析_2022国赛c题matlab_UST数模社_的博客-CSDN博客 2022国赛数学建模A题B题C题D题资料思路汇总 高教社杯_2022国赛c题matlab_UST数模社…

sh 脚本循环语句和正则表达式

目录 1、循环语句 1、for 2、while 3、until 2、正则表达式 1、元字符 2、表示次数 3、位置锚定 4、分组 5、扩展正则表达式 1、循环语句 循环含义 将某代码段重复运行多次&#xff0c;通常有进入循环的条件和退出循环的条件 重复运行次数 循环次数事先已知 循环次…

【SA8295P 源码分析】63 - defconfig 解析 之 修改 Kernel 宏控配置应该修改哪些 config 文件才会生效?

【SA8295P 源码分析】63 - defconfig 解析 之 修改 Kernel 宏控配置应该修改哪些 config 文件才会生效? 二、Kernel defconfig 生成过程分析2.1 kernel/msm-5.4/arch/arm64/configs/autogvm-qgki-debug_defconfig 的生成过程2.2 defconfig 编译实战2.2.1 修改 defconfig、vend…

个人信息保护影响评估主要任务清单

一、整合不同情形下要求的个人信息保护影响评估 随着网信办对个人信息出境安全评估报批/备案设置了整改期限&#xff0c;出境安全评估成为当下的一个热点。但是值得注意的是&#xff0c;并不是只有在个人信息出境的情况下才需要进行个人信息保护影响评估。 根据《个人信息保护…

Appium 2安装与使用java对Android进行自动化测试

文章目录 1、Appium 2.1安装1.1、系统要求1.2、安装Appium2.1服务1.3、安装UiAutomator2驱动1.4、安装Android SDK platform tools1.5、下载OpenJDK 2、Android自动代码例子2.1、安装Android自动化测试元素定位工具Appium Inspector2.2、编写android app自动化测试代码和使用ex…

Python批量爬虫下载文件——把Excel中的超链接快速变成网址

本文的背景是&#xff1a;大学关系很好的老师问我能不能把Excel中1000个超链接网址对应的pdf文档下载下来。虽然可以手动一个一个点击下载&#xff0c;但是这样太费人力和时间了。我想起了之前的爬虫经验&#xff0c;给老师分析了一下可行性&#xff0c;就动手实践了。    没…