Vue学习(六)

Vue封装的过度与动画

  1. 作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。

  2. 图示:

  3. 写法:

    (1)准备好样式:

    • 元素进入的样式:
      v-enter:进入的起点
      v-enter-active:进入过程中
      v-enter-to:进入的终点
    • 元素离开的样式:
      v-leave:离开的起点
      v-leave-active:离开过程中
      v-leave-to:离开的终点
/* 进入的起点,离开的终点 */
.hello-enter,.hello-enter-to{
    transform: translateX(-100%);
}
.hello-enter-active,.hello-leave-active{
    transition: 1s linear;
}
/* 进入的终点,离开的起点 */
.hello-enter-to,.hello-leave{
    transform: translateX(0px);
}

(2)使用<transition>包裹要过度的元素,并配置name属性

	<transition name="hello">
      	<h1 v-show="isShow">你好啊!</h1>
     </transition>

(3)备注:若有多个元素需要过度,则需要使用:<transition-group>,且每个元素都要指定key值。

	<transition-group name="hello" appear>
      <!-- transition-group多个元素过渡  -->
      <h1 v-show="!isShow" key="1">你好啊!</h1>
      <h1 v-show="isShow" key="2">欢迎您!</h1>
    </transition-group>

案例(三种不同的方式)

test1

Test.vue

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <!-- <transition name="hello" :appear="true"></transition> -->
    <transition name="hello" appear>
      <h1 v-show="isShow">你好啊!</h1>
    </transition>

  </div>
</template>

<script>
export default {
  name: 'Test',
  data() {
    return {
      isShow: true,
    };
  },
};
</script>

<style scoped>
h1 {
  background-color: orange;
}
.hello-enter-active{
    animation: atguigu 1s linear;
}
.hello-leave-active{
    animation: atguigu 1s linear reverse;
}
@keyframes atguigu {
  from {
    transform:translateX(-100%) ;
  }
  to {
    transform: translateX(0px);
  }
}
</style>

test2

Test2.vue

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <!-- <transition name="hello" :appear="true"></transition> -->
    <transition-group name="hello" appear>
      <!-- transition-group多个元素过渡  -->
      <h1 v-show="!isShow" key="1">你好啊!</h1>
      <h1 v-show="isShow" key="2">欢迎您!</h1>
    </transition-group>

  </div>
</template>

<script>
export default {
  name: 'Test2',
  data() {
    return {
      isShow: true,
    };
  },
};
</script>

<style scoped>
h1 {
  background-color: orange;
}
/* 进入的起点,离开的终点 */
.hello-enter,.hello-enter-to{
    transform: translateX(-100%);
}
.hello-enter-active,.hello-leave-active{
    transition: 1s linear;
}
/* 进入的终点,离开的起点 */
.hello-enter-to,.hello-leave{
    transform: translateX(0px);
}

</style>

test3

Test3.vue

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <!-- <transition name="hello" :appear="true"></transition> -->
    <transition-group 
      appear
      name="animate__animated animate__bounce" 
      enter-active-class="animate__swing"
      leave-active-class="animate__bounceOutUp"
    >
      <!-- transition-group多个元素过渡  -->
      <h1 v-show="!isShow" key="1">你好啊!</h1>
      <h1 v-show="isShow" key="2">欢迎您!</h1>
    </transition-group>

  </div>
</template>

<script>
import 'animate.css'
export default {
  name: 'Test3',
  data() {
    return {
      isShow: true,
    };
  },
};
</script>

<style scoped>
h1 {
  background-color: orange;
}
</style>

App.vue

<template>
  <div>
    <Test/>
    <Test2/>
    <Test3/>
  </div>
</template>

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

vue脚手架配置代理

方法一

​ 在vue.config.js中添加如下配置:

devServer:{
  proxy:"http://localhost:5000"
}

说明:

  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

方法二

​ 编写vue.config.js配置具体代理规则:

module.exports = {
	devServer: {
      proxy: {
      '/api1': {// 匹配所有以 '/api1'开头的请求路径
        target: 'http://localhost:5000',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api1': ''}
      },
      '/api2': {// 匹配所有以 '/api2'开头的请求路径
        target: 'http://localhost:5001',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}
/*
   changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
   changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
   changeOrigin默认值为true
*/

说明:

  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。

示例

<template>
  <div>
    <button @click="getStudents">获取学生信息</button>
    <button @click="getCars">获取汽车信息</button>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  name: "App",
  methods:{
    getStudents(){
      //加了api前缀就会强制转给api对应的代理服务器,否则会先在其自身中寻找students
      axios.get('http://localhost:8080/api/students').then( 
        response => {                                       
          console.log('请求成功了',response.data)
        },
        error => {
          console.log('请求失败了',error.message)
        }
      )
    },
    getCars(){
      axios.get('http://localhost:8080/foo/Cars').then(
        response => {
          console.log('请求成功了',response.data)
        },
        error => {
          console.log('请求失败了',error.message)
        }
      )
    }
  }
};
</script>

github搜索案例

List.vue

<template>
  <div class="row">
      <!-- 展示用户列表 -->
    <div class="card" v-show="info.users.length" 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>
  </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组件,收到数据',dataObj)
                this.info = {...this.info,...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>

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"
      />&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 => {
                    //请求成功后更新List的数据
                    console.log("请求成功!")
                    this.$bus.$emit('updateListData',{isLoading:false,errMsg:'',users:response.data.items})
                },
                error =>{
                    //请求失败后更新List的数据
                    console.log("请求失败!")
                    this.$bus.$emit('updateListData',{isLoading:false,errMsg:error.message,users:[]})
                }
            )
        }
    },
  };
</script>

<style>
</style>

App.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>

效果图:
最初:
在这里插入图片描述
查询过程:
在这里插入图片描述
查到后:
在这里插入图片描述

插槽

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

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

  3. 使用方式:

默认插槽

 	 父组件中:
              <Category>
                 <div>html结构1</div>
              </Category>
 	 子组件中:
              <template>
                  <div>
                     <!-- 定义插槽 -->
                     <slot>插槽默认内容...</slot>
                  </div>
              </template>

示例:
Category.vue

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

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

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

App.vue

<template>
    <div class="container">
      <Category title="美食" :listData='foods'>
        <img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
      </Category>
      <Category title="游戏" :listData='games'>
        <ul>
          <li v-for="g,index in games" :key="index">{{g}}</li>
      </ul>
      </Category>
      <Category title="电影" :listData='films'>
        <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:['红色警戒','穿越火线','超级玛丽'],
      films:['《教父》','《拆弹专家》','《中国医生》']

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

效果图:
在这里插入图片描述

② 具名插槽:

	 父组件中:
              <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>

示例:
Category.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:['listData','title']
}
</script>

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

App.vue

<template>
    <div class="container">
      <Category title="美食" :listData='foods'>
        <img slot="center" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
        <a slot="footer" href="http://baidu.com">更多美食</a>
      </Category>
      <Category title="游戏" :listData='games'>
        <ul slot="center">
          <li v-for="g,index in games" :key="index">{{g}}</li>
      </ul>
      <div class="foot" slot="footer">
        <a href="http://baidu.com">单机游戏</a>
        <a href="http://baidu.com">网络游戏</a>
      </div>
      </Category>
      <Category title="电影" :listData='films'>
        <video slot="center" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
        <template v-slot:footer>
          <div class="foot">
            <a href="http://baidu.com">经典</a>
            <a href="http://baidu.com">热门</a>
            <a href="http://baidu.com">推荐</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:['红色警戒','穿越火线','超级玛丽'],
      films:['《教父》','《拆弹专家》','《中国医生》']

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

作用域插槽:

  1. 理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)

  2. 具体编码:

		父组件中:
         		<Category>
         			<template scope="scopeData">
         				<!-- 生成的是ul列表 -->
         				<ul>
         					<li v-for="g in scopeData.games" :key="g">{{g}}</li>
         				</ul>
         			</template>
         		</Category>
         
         		<Category>
         			<template slot-scope="scopeData">
         				<!-- 生成的是h4标题 -->
         				<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
         			</template>
         		</Category>
         		
         子组件中:
                 <template>
                     <div>
                         <slot :games="games"></slot>
                     </div>
                 </template>
         		
                 <script>
                     export default {
                         name:'Category',
                         props:['title'],
                         //数据在子组件自身
                         data() {
                             return {
                                 games:['红色警戒','穿越火线','劲舞团','超级玛丽']
                             }
                         },
                     }
                 </script>

示例:
Category.vue

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

<script>
export default {
    name:'Category',
    props:['title'],
    data(){
    return{
      games:['红色警戒','穿越火线','超级玛丽'],
    }
  }
}
</script>

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

App.vue

<template>
    <div class="container">
      <Category title="游戏">
        <template scope="xyy">
         <ul>
          <li v-for="g,index in xyy. games" :key="index">{{g}}</li>
        </ul>
        </template>
      </Category>

      <Category title="游戏">
       <template scope="{games}">
        <ol>
          <li style="color:red" v-for="g,index in games" :key="index">{{g}}</li>
        </ol>
       </template>
      </Category>

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

<script>
import Category from './components/Category.vue'
export default {
  name: "App",
  components:{Category},
};
</script>
<style>
  .container,.foot{
    display: flex;
    justify-content: space-around;
  }
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值