Vue.js之组件化应用构建+vue数据请求

本文记录vue组件系统下的创建与使用,包含组件之间如何传值;vue的数据请求。参考来源于IT营的大地老师关于Vue教程,需要的可留言邮箱,我会直接发百度云链接,无偿。

 关于组件,借用官方的介绍,很清楚了,下图:

 组件的注册与使用:

  1. 定义组件
  2. 引入组件
  3. 挂载组件
  4. 使用组件

举个例子,定义一个主页组件Home.vue,然后在根组件App.vue中使用这一组件。

首先是定义组件,先在src文件夹下新建一个components文件夹用来存放组件。进入components文件夹新建Home.vue。自己定义的组件与根组件一样,有template标签,也可有script标签、style标签。

Home.vue

<template>
  <div>
    <h2>{{ msg }}</h2>
  </div>
</template>

<script>
  export default{
      data(){
          return{
              msg:'这是一个Home组件,在根组件中进行挂载'
          }
      }
  }
</script>

定义好组件之后,在需要使用此组件的组件中进行自定义组件的引入、挂载、使用。例子中我们需要在根组件中使用自定义Home组件,如下图所示:(emmm,忽略IDE背景)

搞定,看看效果:(由于在demo中还有其他组件,页面上其他组件内容已马赛克)

以上。 


组件中数据和方法的传递(分以下四种情况):

  1. 父组件传递数据和方法(甚至是整个父组件实例)到子组件
  2. 父组件主动获取子组件的数据和方法
  3. 子组件主动获取父组件的数据和方法
  4. 非父子组件之间数据的传递

第一种, 父组件传递数据和方法(甚至是整个父组件实例到子组件

分三步走:1.父组件调用子组件的时候,在标签中绑定动态属性;2.在子组件中通过props去接收父组件传递过来的数据或方法。3.和data里面的数据同样使用方式去使用,模板中直接用{{ props中的自定义命名 }},在<script>中用this.props中的自定义命名。下面例子以Home.vue为父组件,Header.vue为子组件,父组件传递一个数据和一个方法到子组件。

Home.vue(父组件)

<template>
  <div>
        <!-- 模板中使用子组件 -->
        <!-- 在使用时给标签绑定动态属性,将数据传至子组件 -->
        <!-- =号前是自定义命名,引号内是父组件中需要传递的数据或方法 -->
    <v-header :fromHomeNews="homeNews" :fromHomeFunction="homeRun"></v-header>
  </div>
</template>

<script>
  import Header from './Header.vue';    //引入子组件
  export default{
      data(){
          return{
              homeNews:'这条数据来自Home组件'
          }
      },
      methods:{
        homeRun:function () {
          alert('这个消息来自Home组件中的方法');
        }
      },
      components:{
          'v-header':Header,    //挂载子组件
      }
  }
</script>

Header.vue(子组件) 

<template>
  <div id="headMsg">
    <h1>{{ headerMsg }}</h1>
    <p>{{ fromHomeNews }}</p>   <!-- 在子组件的模板中使用父组件传递过来的数据 -->
    <button @click="showHomeData()">点击显示父组件数据</button>
    <button @click="fromHomeFunction()">点击调用父组件方法</button>
  </div>
</template>

<script>
  export default{
    data(){
        return{
            headerMsg:'这是头部组件,在Home组件中进行挂载'
        }
    },
    props:['fromHomeNews','fromHomeFunction']    //接收父组件传递过来的数据和方法
    ,methods:{
        showHomeData:function () {
            //<script>中使用父组件传递过来的数据
          alert(this.fromHomeNews);
        }
    }
  }
</script>

<style>
  #headMsg{
    color: red;
    border-bottom: 1px solid #eee;
  }
</style>

效果如下: 

点击第一个按钮:

 

点击第二个按钮: 

如果觉得这种父传子的方法很繁杂,那就对了。毕竟需要在标签中绑定那么多数据,不可能需要传一百个那就绑定一百个,这不现实。所以,在父组件向子组件传递数据中,有一种方法,最为简单粗暴,就是直接将整个父组件实例传过去(视情况而定,这种不代表就是最好)。举例还是由Home.vue向Header.vue传递,如下代码所示:

Home.vue

<template>
  <div>
    <!-- 模板中使用子组件 -->
    <!-- 在使用时给标签绑定动态属性,将数据传至子组件 -->
    <!-- =号前是自定义命名,引号内是父组件中需要传递的数据或方法 -->
    <!-- :home="this"是直接把父组件中所有数据和方法都传递过去 -->
    <v-header :fromHomeNews="homeNews" :fromHomeFunction="homeRun" :home="this"></v-header>
  </div>
</template>

<script>
  import Header from './Header.vue';    //引入子组件
  export default{
    data(){
      return{
        homeNews:'这条数据来自Home组件',
      }
    },
    methods:{
      homeRun:function () {
        alert('这个消息来自Home组件中的方法');
      }
    },
    components:{
      'v-header':Header,    //挂载子组件
    }
  }
</script>

Header.vue

<template>
  <div id="headMsg">
    <h1>{{ headerMsg }}</h1>
    <p>{{ fromHomeNews }}</p>   <!-- 在子组件的模板中使用父组件传递过来的数据 -->
    <p>{{ home.homeNews }}</p>  <!-- 两个p标签中都是引用同一个来自父组件的数据 -->
    <button @click="showHomeData()">点击显示父组件数据</button>
    <!-- 下面两个按钮执行的都是来自父组件的同一个方法 -->
    <button @click="fromHomeFunction()">点击调用父组件方法</button>
    <button @click="home.homeRun()">点击调用父组件方法</button>
  </div>
</template>

<script>
  export default{
    data(){
      return{
        headerMsg:'这是头部组件,在Home组件中进行挂载'
      }
    },
    props:['fromHomeNews','fromHomeFunction','home']    //接收父组件传递过来的数据和方法
    ,methods:{
      showHomeData:function () {
        //<script>中使用父组件传递过来的数据(两个写法都可以,因为在父组件中已经全部传过来了)
//        alert(this.fromHomeNews);
        alert(this.home.homeNews);
      }
    }
  }
</script>

<style>
  #headMsg{
    color: red;
    border-bottom: 1px solid #eee;
  }
</style>

注意:传递实例跟传其他数据或者方法一样,都是在使用模板标签的时候绑定属性,但是绑定的内容只能是“this”,这个“this”代表的是当前父组件整个实例。接收也是同样在子组件的props数组中接收。但是在子组件用的时候就有点不同了,需要在指代this的自定义命名后加上父组件中的数据名或方法名。比如例子中Header.vue里面的homeNews和homeRun()都是在父组件中定义的数据名和方法名。

第二种, 父组件主动获取子组件的数据。

分两步走:父组件在调用子组件模板时,给子组件标签添加ref属性。如:<v-header ref="header"></v-header>。再通过this.$refs.header.数据名/方法名的形式去调用。

第三种, 子组件主动获取父组件的数据。

一步走就行,即直接以this.$parent.数据名/方法名的形式去调用。前提是子组件已经在父组件中挂载(这句好像是废话。。)

第二第三种合为一个例子,代码如下:

Home.vue

<template>
  <div>
    <v-header ref="header"></v-header>
    <label>父组件按钮:</label>
    <button @click="getChildData()">点击主动获取子组件的数据</button>
  </div>
</template>

<script>
  import Header from './Header.vue';    //引入子组件
  export default{
    data(){
      return{
        homeNews:'这条数据来自Home组件',
      }
    },
    methods:{
      homeRun:function () {
        alert('这个消息来自Home组件中的方法');
      },
      getChildData:function () {
        alert(this.$refs.header.headerNews);
      },
    },
    components:{
      'v-header':Header,    //挂载子组件
    }
  }
</script>

Header.vue

<template>
  <div id="headMsg">
    <h1>{{ headerMsg }}</h1>
    <label>子组件按钮:</label>
    <button @click="getParentData()">点击主动获取父组件的数据</button>
  </div>
</template>

<script>
  export default{
    data(){
      return{
        headerMsg:'这是Header组件,在Home组件中进行挂载',
        headerNews:'这条数据是子组件中的数据',
      }
    },
    methods:{
      headerRun:function () {
        alert('这个消息来自header组件中的方法');
      },
      getParentData:function () {
        alert(this.$parent.homeNews);   //this.$parent.homeNews 主动获取父组件中的homeNews
      }
    }
  }
</script>

<style>
  #headMsg{
    color: red;
    border-bottom: 1px solid #eee;
  }
</style>

注意:主动获取的方式只能在组件的<script>标签中使用,在<template>中不生效。

效果如下:

点击子组件按钮:

点击父组件按钮: 

 第三种, 非父子组件之间数据的传递

这种非父子组件传值的方式实际上并不常用,后面会有别的方式。主要是记录一下。此种方式主要分两大部分:首先新建js文件并在其中一次依次进行vue的引入、vue的实例化、暴露此实例,然后在组件中按需求进行广播或者接受数据,其中广播方式为:VueEvent.$emit('自定义名称',数据);接受方式为:VueEvent.$on('自定义名称',参数为被传递数据的回调函数);下面以Home组件广播数据,somgNews组件接收数据为例:

新建js文件名为VueEvent.js

//引入Vue
import Vue from 'vue';
//实例化Vue
var VueEvent = new Vue();
//暴露这个实例
export default VueEvent;

/*
*   使用方法:
*   在需要广播或者接收广播的组件中引入这个实例;
*   广播:VueEvent.$emit('自定义名称',数据);
*   接收广播: VueEvent.$on('自定义名称',参数为被传递数据的回调函数)
*/

Home.vue

<template>
  <div id="homeArea">
    <h2>{{ homeMsg }}</h2>
    <button v-on:click="toNews()">广播Home组件数据</button>
  </div>
</template>

<script>
  import VueEvent from '../model/VueEvent';
  export default{
    data(){
      return{
        homeMsg:'我是Home组件',
      }
    },
    methods:{
      toNews:function () {
        VueEvent.$emit('to-News',this.homeMsg);    //广播homeMsg
      }
    }
  }
</script>

<style>
  #homeArea{
    border-bottom: 1px solid #d4d4d4;
  }
</style>

someNews.vue

<template>
    <div>
      <h2>{{ newsMsg }}</h2>
    </div>
</template>

<script>
  import VueEvent from '../model/VueEvent';
    export default {
        data(){
            return {
                newsMsg:'我是someNews组件'
            }
        },
      mounted(){
            VueEvent.$on('to-News',function (data) {
              alert('someNews组件弹出框:'+data);    //data参数即为所接收数据
            })
      }
    }
</script>

效果如下: (点击广播按钮)

以上。 


vue数据请求:

关于数据请求有很多第三方插件,官方也提供了一个叫vue-resource的请求插件,github搜索vue-resource,第一个:

github上的README文件中有介绍插件的安装与用法:

这里我使用npm安装方式,cmd进入到项目文件夹,输入如下命令:

npm install vue-resource --save

注意一下官方命令并没有在后面加上--save。加上--save是为了让它写入依赖中,方便以后项目转移时进行npm install的时候会自动添加这一插件。 

插件安装完成之后,需要在main.js文件中引入vue-resource:

接下来在模板中使用这一插件。先写一个button按钮触发请求数据方法,将接受的数据存入list数组中,并且在ul>li中渲染出来。代码如下:

<template>
  <div>
    <button v-on:click="requestSource()">请求数据</button>
    <ul>
      <li v-for="item in list">{{ item.title }}</li>
    </ul>
  </div>
</template>

<script>
  export default{
      data(){
       return{
           list:[]
       }
      },
    methods:{
          requestSource:function () {
            var urlApi = 'https://api.douban.com//v2/movie/top250';
            this.$http.get(urlApi).then(function (response) {
              console.log(response);
              //this.list = response.body.result;    //赋值给list
            },function (err) {
              console.log(err);
              alert('请求数据失败');
            });
          }
    },
    mounted(){
            //也可以在生命周期函数中调用请求数据方法,使得页面一进来就请求数据并且渲染出来
          this.requestSource();    
    }
  }
</script>

但是由于跨域请求,所以我们需要用jsonp的方式去解决跨域问题,代码修改如下: 

<template>
  <div>
    <hr>
    <h2>这是一个请求数据组件,在Home组件进行挂载</h2>
    <button v-on:click="requestSource()">{{ msg }}</button>
    <ul>
      <li v-for="item in list">{{ item.title }}</li>
    </ul>
  </div>
</template>

<script>
  export default{
      data(){
       return{
           msg:'请求数据',
           list:[]
       }
      },
    methods:{
          requestSource:function () {
            var urlApi = 'https://api.douban.com//v2/movie/top250';
            //解决跨域问题
            this.$http.jsonp(urlApi,{},
              {
                headers: {},
                emulateJSON: true }).then(function (response) {
              console.log(response);
              this.list = response.body.subjects;
            },function (err) {
              console.log(err);
              alert('请求数据失败');
            });
          }
    },
    mounted(){
          this.requestSource();
    }

  }
</script>

页面一进来就会请求数据,不用点击按钮。效果如下图(这里是取到数据中的title字段显示到页面之中): 

以上。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值