八、组件之间的通信
父组件向子组件传递值:通过props属性,具体参看
子组件向父组件传递值:通过this.$emit("事件名","值")
事件传值
示例:将子组件中的频道id(channelId)传递到父组件中
Channels组件
<template>
<div>
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
>
<el-menu-item :index="i.toString()
" v-for="(item,i) in showChannels" :key="item.channelId"
@click="changeChannel(item.channelId)"
>{{item.name}}</el-menu-item>
<el-menu-item><a @click="handleFold()">{{isFold?"折叠":"展开"}}</a></el-menu-item>
</el-menu>
</div>
</template>
<script>
import {getNewsChannels} from '../services/NewsService'
export default {
data() {
return {
chooseId:"",
activeIndex:"0",
isFold:false,
channels:[],
};
},
methods: {
handleFold(){
this.isFold = !this.isFold;
},
handleSelect(key, keyPath) {
console.log(key, keyPath);
},
changeChannel(channelId){
console.log("子组件页面---->" + channelId);
this.chooseId = channelId;
//给组件注册change事件,并传递this.chooseId
this.$emit("change",this.chooseId);
}
},
computed:{
showChannels(){
if(this.isFold){ //如果没有折叠显示全部数据
return this.channels;
}
else{ //如果折叠显示6条新闻频道数据
return this.channels.slice(0,6);
}
},
},
async created() {
let resp = await getNewsChannels();
console.log("axios获取的远程数据格式--->" + resp);
this.channels = resp;
//调用changeChannel方法,目的是页面出现就传递ChannelId
this.changeChannel(this.chooseId);
},
};
</script>
<style></style>
相对于之前的代码,这段代码主要下面的方法
changeChannel(channelId){
console.log("子组件页面---->" + channelId);
this.chooseId = channelId;
//给组件注册change事件,并传递this.chooseId
this.$emit("change",this.chooseId);
}
this.$emit("change",this.chooseId);
就是将change事件注册给子组件,那么父页面在调用子组件的时候,就需要调用@change
事件
父组件App.vue
<template>
<div id="app">
<el-container>
<el-header>
</el-header>
<el-main>
<!-- 调用子组件,并且调用子组件的change事件 -->
<Channels @change="handleChange"></Channels>
</el-main>
</el-container>
</div>
</template>
<script>
import Channels from "./components/Channels";
export default {
name: "App",
methods: {
handleChange(chooseId){
console.log("主页面---->" + chooseId);
}
},
components: { Channels },
};
</script>
<style>
.el-header,
.el-footer {
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
color: #333;
text-align: center;
}
</style>
相对于之前的代码,主要也是多了一个方法
handleChange(chooseId){
console.log("主页面---->" + chooseId);
}
这个方法主要用于子组件事件的调用
<Header @change="handleChange"></Header>
handleChange方法里面的参数chooseId,会由子组件传递过来
显示新闻列表
父组件中已经获取了频道id,那么,我们可以通过这个频道id,获取这个频道下所有的新闻列表
当然,先做好基本的测试,写好service获取远程API数据
可以到阿里云中先观察必须的API,然后封装我们自己的方法 https://market.aliyun.com/products/57126001/cmapi011150.html?spm=5176.2020520132.101.1.ee2e1a46tkPOsZ#sku=yuncode515000003
获取新闻列表的Service方法
export async function getNewsList(channelId,page=1,limit=10){
let resp = await axios.get("http://ali-news.showapi.com/newsList",{
headers:{
Authorization:`APPCODE 176eadd6b4654cd5a9328c74a9025c37`
},
params:{
channelId,
page,
maxResult:limit,
needAllList:false,
needContent:1
}
});
return resp.data.showapi_res_body.pagebean;
}
创建显示新闻列表的组件NewList
<template>
<div>
<div class="news-item-normal" v-for="(item) in news" :key="item.id">
<div class="words">
<h1 class="title">
<a :href="item.link">{{item.title}}</a>
</h1>
<div class="aside">
<span>{{item.channelName}}</span>
<span>{{item.source}}</span>
<span>{{item.pubDate}}</span>
</div>
<div class="content">
{{item.content}}
</div>
</div>
</div>
</div>
</template>
<script>
import {getNewsChannels,getNewsList} from '@/services/NewsService'
export default {
data() {
return {
news:[],
}
},
async created() {
var resp = await getNewsList("5572a108b3cdc86cf39001cd");
console.log(resp.contentlist);
this.news = resp.contentlist;
},
}
</script>
<style scoped>
.news-item-normal {
border-bottom: 1px solid #ccc;
overflow: hidden;
padding: 20px 0;
}
.image {
width: 150px;
height: 150px;
border: 1px solid #ccc;
border-radius: 4px;
float: left;
margin-right: 20px;
}
.image img {
width: 100%;
height: 100%;
object-fit: contain;
}
.title {
font-size: 1.5em;
}
.aside {
font-size: 14px;
color: #888;
}
.aside span {
margin-right: 15px;
}
.content {
max-height: 100px;
overflow: hidden;
line-height: 2;
}
</style>
当然,接下来就需要在App.vue中加入NewList.vue组件即可
<template>
<div id="app">
<el-container>
<el-header>
<!-- 调用子组件,并且调用子组件的change事件 -->
<Header @change="handleChange"></Header>
</el-header>
<el-main>
<NewList></NewList>
</el-main>
</el-container>
</div>
</template>
<script>
import Header from "./components/Header";
import NewList from "./components/NewList";
export default {
name: "App",
methods: {
handleChange(chooseId){
console.log("主页面---->" + chooseId);
}
},
components: { Header,NewList },
};
</script>
<style>
...省略
</style>
传递频道id
上面的新闻列表组件写了一个固定的频道id,现在需要点哪个频道,就显示哪个频道的新闻列表,需要将频道id传递过来,改写新闻列表页面,传递频道id,当然,也能在父页面直接获取频道列表,然后直接传递频道列表数组过来
修改App.vue
<template>
<div id="app">
<el-container>
<el-header>
<!-- 调用子组件,并且调用子组件的change事件 -->
<Header @change="handleChange"></Header>
</el-header>
<el-main>
<!-- 调用子组件,传递新闻列表数组 -->
<NewList :news="news"></NewList>
</el-main>
</el-container>
</div>
</template>
<script>
import Header from "./components/Header";
import NewList from "./components/NewList";
import { getNewsList } from './services/NewsService';
export default {
name: "App",
components: { Header,NewList },
data(){
return {
chooseId:0,
news:[],
}
},
methods: {
async handleChange(chooseId){ //切换频道的时候传递频道id并调用远程数据
this.chooseId = chooseId;
console.log("主页面---->" + chooseId);
let resp = await getNewsList(this.chooseId);
this.news = resp.contentlist;
}
},
};
</script>
<style>
...省略
</style>
修改NewList.vue页面
<template>
...省略
</template>
<script>
export default {
props:{
news:{
type:Array,
default:function(){return [];}
}
}
}
</script>
<style scoped>
...省略
</style>
当然现在这个样子,必须界面要点击新闻频道的名字,才会显示下面的新闻列表,并没有一开始就直接显示新闻列表。这是因为我们只是和点击事件绑定了channelId的传递,还应该在一开是created() Channels组件的时候,就应该传递channelId Channels.vue
...省略其他代码
async created() {
let resp = await getNewsChannels();
this.channels = resp;
//调用changeChannel方法,目的是页面出现就传递ChannelId
this.changeChannel(this.chooseId);
},
Comments