Vue2(十一):脚手架配置代理、github案例、插槽

一、脚手架配置代理

1.回顾常用的ajax发送方式:

(1)xhr

比较麻烦,不常用

(2)jQuery

核心是封装dom操作,所以也不常用

(3)axios

优势:体积小、是promise风格的、支持请求拦截器和响应拦截器

(4)fetch

2.3都是封装xhr的,fetch跟xhr平级,直接在window身上就能找到,而且也是promise风格的,但是不兼容,ie肯定不能用;它会把你返回的数据包两层,所以不如axios常用。

2.引出问题

点击按钮获取学生信息,app.vue:

复制代码
import axios from 'axios'
import { response } from 'express'
export default {
name:'App',
methods:{
  getStudent(){
    axios.get('http://localhost:5000/students'),then(
      response=>{
        console.log('请求成功了',response.data)
        //response是一个响应对象。data里面的东西才是response想给你的
      },
      error=>{
        console.log('请求失败了',error.message)
        //maeeage失败的原因
      }
    )
  }
}
}

点击按钮之后页面报错,出现、、、cors、、、Access-Control-Allow-Oringin说明跨域了,协议、域名、端口号出现不一样的,我们所在的端口号是8080,向端口号5000的要数据,5000给8080了,然后8080发现跨域了就没有给你数据,解决跨域的问题:

1.cors(写服务器的人在服务器加几个响应头)

5000返回的时候还携带几个特殊的响应头,8000看见就给你了

2.jsonp(借助script 的src属性)

src属性在引入外部资源的时候不受同源限制,但是得前端后端一起配合,而且它只能解决get请求的问题,开发不常用但是面试经常问,很巧妙的用法

3.配置一个代理服务器

代理服务器是一个中间人,但是它所处的位置跟我们一样(8080),粉色那个跟我们肯定是同域的,那粉色跟蓝色呢?他俩都是服务器,服务器和服务器之间传输局不用ajax,用的就是http传就完事了。那粉色的8080服务器得怎么开啊?1.nginx,学习成本大偏后端 2.vue-cli,借助vue脚手架。

然后我们就来配置一下代理服务器

(1)方式一:

在vue.config.js:

它的8080不用你管,你只需要告诉这个代理服务器一会要把请求转发给谁就ok,后面具体路径不用写,写到端口号就行

复制代码
//开启服务代理
devServer:{
  proxy:'htp://localhost:5000'
}

app.vue

复制代码
methods:{
  getStudent(){
    axios.get('http://localhost:8080/students').then(
      response=>{
        console.log('请求成功了',response.data)
        //response是一个响应对象。data里面的东西才是response想给你的
      },
      error=>{
        console.log('请求失败了',error.message)
        //maeeage失败的原因
      }
    )
  }
}

而且这个中间代理也不是什么时候都会转发请求的,如果粉色的自己本身就有就不会往5000找了,public里面文件都算是8080有的。

1、优点:配置简单,请求资源时直接发给前端(8080)即可。

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

3、工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)。

(2)方式二

vue.config.js:

复制代码
devServer:{
  proxy:{
    '/ttt':{ //请求前缀,想走代理就在请求的前面加/???,就把东西转发给target
      target:'http://localhost:5000',
      pathRewrite:{'^/ttt':''},
      //不加这个配置粉色找蓝色的时候默认找的/ttt/server1
      ws:true ,//用于支持websocket
      changeOrigin:true//用于控制请求头的host值
      //这个是告诉5000我也来自5000(是true就撒谎来自5000,false就是来自8080),防止5000用不了设置true比较好
    },
    '/hhh':{ 
      target:'http://localhost:5001',
      pathRewrite:{'^/hhh':''},
      ws:true ,
      changeOrigin:true
    },
  }
}

app:

复制代码
getStudent(){
    axios.get('http://localhost:8080/ttt/students').then(
      //前缀就加在端口号后面,后面正常写
      response=>{
        console.log('请求成功了',response.data)
        //response是一个响应对象。data里面的东西才是response想给你的
      },
      error=>{
        console.log('请求失败了',error.message)
        //maeeage失败的原因
      }
    )
  },
  getCar(){
    axios.get('http://localhost:8080/hhh/cars').then(
      //前缀就加在端口号后面,后面正常写
      response=>{
        console.log('请求成功了',response.data)
        //response是一个响应对象。data里面的东西才是response想给你的
      },
      error=>{
        console.log('请求失败了',error.message)
        //maeeage失败的原因
      }
    )
  }

如果我自己也有个students它也不会来拿我这个信息,因为加了/ttt就强制去5000那里拿数据了,所以这种就更灵活。

1、优点:可以配置多个代理,且可以灵活的控制请求是否走代理。

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

二、github案例

如果第三方库你写在assets里面了就得用import 引用,用import引用会很严重的检查,有某些字体你没有但是你引用了那就显示不出来,但是link方法没事,你没有但是引用了就不显示呗

所以像这种引入了外部资源的就不适合用assets/css/里面,那就放在public/css,然后在index.html中link引用一下,他里面引用了app也能用

接口https虽然案例来说跨域了,但是人家的工程师用cors已经解决了不用我们担心

list首先展示欢迎,用户搜索之后显示 正在加载中 ,加载完毕显示users,加载失败显示error

那怎么判断该显示啥呢?数据驱动页面展示

1.app.vue

复制代码
<template>
  <div class="container">
    <mySearch />
    <myList />
  </div>
</template>

<script>
import mySearch from "./components/mySearch.vue";
import myList from "./components/myList.vue";
export default {
  name: "App",
  components: { mySearch, myList },
};
</script>

<style>
</style>

2.myList.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">欢迎!</h1>
    <!-- 加载中 -->
    <h1 v-show="info.isLoading">加载中······</h1>
    <!-- 错误信息 -->
    <h1 v-show="info.errMsg">{{ info.errMsg }}</h1>
    <!-- 都一样就不一个一个写了,但是这次也不用item,直接v-for -->
  </div>
</template>

<script>
export default {
  name: "myList",
  data() {
    return {
      info: {
        isFirst: true, //是不是初次展示
        isLoading: false, //点击按钮之后才加载
        errMsg: "", //不能用布尔值了,得看看是网差还是别的原因呢导致的
        users: [],
        //这些东西都得听search的,情况不同他们几个值也变
      },
    };
  },
  mounted() {
    this.$bus.$on('updateListData', (dataObj) => {
      this.info={...this.dataObj,...dataObj}//es6规则,俩人都有的按后边来,前面没有的要后面的
      //这里不要this.data=dataObj,更不能this._data,赋值过去动了原本配置的getter、setter
    });
  },
};
</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>

3.mySearch.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'
//import { response } from 'express';
export default {
  name:'mySearch',
  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=>
        {
          this.$bus.$emit('updateListData',{isLoading:false,errMsg:'',users:response.data.items})
          // 就最开始欢迎一下,之后就不用了,但是直接不写之后就少一个属性,用es6语法解决
          console.log('请求成功',response.data.items)
          this.$bus.$emit('getUsers',response.data.items)
        },
        error=>{
          this.$bus.$emit('updateListData',{isLoading:false,errMsg:error.message,users:[]})
          console.log('请求失败',error.message)
        }
      )
      // 直接等于this.??他肯定不按js给你解析,模版字符串然后$
    }
  }
};
</script>

<style>
</style>

4.vue-resource

也是对xhr的封装,安装插件 :npm i vue-resource

就是把axios替换成了this.$http,其他的都一样

main.js引入插件:import vueResource from 'vue-resource'

使用插件:Vue.use(vueResource)

维护的不频繁用的不多

三、插槽

1.默认插槽

如果我想在最小的组件(重复的)的其中一个里面添加图片,和其他组件都不一样的话,我直接在<category> <img、、、></category>这样写出不来图片,因为人家解析到img之后不知道来到category.vue里人家就不知道把img给你放哪儿了。

用一个特殊的标签slot,告诉人家识别完不知道放哪儿的标签放在哪个位置

(1)app.vue

复制代码
<template>
  <div class="container">
    <myCategory title="美食">
      <img src="http://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="" />
    </myCategory>
    <myCategory title="游戏">
      <ul>
        <li v-for="(g, index) in games" :key="index">{{ g }}</li>
      </ul>
    </myCategory>
    <!-- 这三个的样式都是解析完之后才塞到myCategory里面去的,所以script可以直接写在app里 -->
    <myCategory title="电影">
      <video
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck.bunny.mp4"
      ></video>
    </myCategory>
    <!-- :foods=foods那得传太多了,很麻烦 -->
  </div>
</template>

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

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

(2)myCategory.vue

复制代码
<template>
  <div class="category">
    <h3>{{ title }}</h3>
    <slot>图片加载不出来会看见这些文字</slot>
    <!-- 挖坑等组件的使用者进行填充 -->
  </div>
</template>

<script>
export default {
  name: "myCategory",
  props: ["listData", "title"],
};
</script>

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

2.具名插槽

刚才那个只有一个,直接用的slot,具名插槽就是具有名字的插槽

app:

复制代码
<template>
  <div class="container">
    <myCategory title="美食">
      <img
        slot="center"
        src="http://s3.ax1x.com/2021/01/16/srJlq0.jpg"
        alt=""
      />
      <a slot="footer" href="">更多美食</a>
    </myCategory>
    <myCategory title="游戏">
      <ul slot="center">
        <li v-for="(g, index) in games" :key="index">{{ g }}</li>
      </ul>
      <div class="foot" slot="footer">
        <a href="">单机游戏</a>
        <a href="">更多美食</a>
      </div>
      <!-- 这个可以追加 -->
    </myCategory>
    <!-- 这三个的样式都是解析完之后才塞到myCategory里面去的,所以script可以直接写在app里 -->
    <myCategory title="电影">
      <video
        slot="center"
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck.bunny.mp4"
      ></video>
      <template v-slot:footer>
        <!-- 这样slot写一次就可以了  因为template slot就可以这样写了,只有它行-->
        <div class="foot">
          <a href="">单机游戏</a>
          <a href="">更多美食</a>
          <a href="">更多美食</a>
        </div>
        <h4>欢迎前来观影</h4>
      </template>
    </myCategory>
    <!-- :foods=foods那得传太多了,很麻烦 -->
  </div>
</template>

mycategory:

复制代码
<template>
  <div class="category">
    <h3>{{ title }}</h3>
    <slot name="center">图片加载不出来会看见这些文字</slot>
    <slot name="footer">图片加载不出来会看见这些文字</slot>
    <!-- 挖坑等组件的使用者进行填充 -->
  </div>
</template>

3.作用域插槽

现在我们只留下游戏重复三个,然后设计第一个是无序列表,第二个有序,第三个每一个游戏都是h4标题

我把数据交给了插槽的使用者,根据数据所生成的结构由使用者来定

app:

复制代码
<template>
  <div class="container">
    <myCategory title="游戏">
      <template scope="atguigu">
        <!-- atguigu收过来的是一个对象 -->
        <ul>
          <li v-for="(g, index) in atguigu.games" :key="index">{{ g }}</li>
        </ul>
      </template>
    </myCategory>

    <myCategory title="游戏">
      <template scope="{games}">
        <!-- 结构赋值 -->
        <!-- atguigu收过来的是一个对象 -->
        <ol>
          <li v-for="(g, index) in games" :key="index">{{ g }}</li>
        </ol>
      </template>
    </myCategory>

    <myCategory title="游戏">
      <template slot-scope="{games}">
        <h4 v-for="(g, index) in games" :key="index">{{ g }}</h4>
      </template>
    </myCategory>
  </div>
</template>

<script>
import myCategory from "./components/myCategory.vue";
export default {
  name: "App",
  components: { myCategory },
};
</script>

<style>
.container,
.foot {
  display: flex;
  justify-content: space-around;
}
img {
  width: 100%;
}
video {
  width: 100%;
}
h4 {
  text-align: center;
}
</style>

category:

复制代码
<template>
  <div class="category">
    <h3>{{ title }}</h3>
    <slot :games="games">我是默认内容</slot>
    <!-- 我在这里写了一个games,那么它就把games传给了插槽的使用者app里 -->
  </div>
</template>

<script>
export default {
  name: "myCategory",
  props: ["listData", "title"],
  data() {
    return {
      games: ["战神4", "极品飞车", "鬼泣", "超级玛丽"],
    };
  },
};
</script>

<style>
.category {
  background-color: aqua;
  width: 200px;
  height: 300px;
}
h3 {
  text-align: center;
  background-color: orange;
}
</style>
相关推荐
草梅友仁1 小时前
AI 图片文字翻译与视频字幕翻译工具推荐 | 2025 年第 23 周草梅周报
开源·github·aigc
qianmoQ5 小时前
GitHub 趋势日报 (2025年06月04日)
github
abcnull7 小时前
github中main与master,master无法合并到main
git·github
星哥说事7 小时前
使用VuePress2.X构建个人知识博客,并且用个人域名部署到GitHub Pages中
开源·github
勤劳打代码8 小时前
步步为营 —— Github Connection refused 分层诊断
github
寻月隐君9 小时前
深入解析 Rust 的面向对象编程:特性、实现与设计模式
后端·rust·github
qianmoQ1 天前
GitHub 趋势日报 (2025年05月31日)
github
油泼辣子多加1 天前
2025年06月06日Github流行趋势
github
粥里有勺糖1 天前
视野修炼-技术周刊第122期 | 发光图片制作
前端·javascript·github
qianmoQ1 天前
GitHub 趋势日报 (2025年06月05日)
github