aaaa.png

1.1.数据接口

聚合数据:https://www.juhe.cn/ 申请 “新闻头条” 数据接口:https://www.juhe.cn/docs/api/id/235 (不可直接跨域访问)

注意:按照聚合数据网站的规定,进行注册以及实名认证,然后申请 “新闻头条” 数据接口。

1.2.工程目录结构

10.项目案例-头条新闻 - 图2

1.3.package.json文件

  1. {
  2. "name": "topnews",
  3. "version": "0.1.0",
  4. "private": true,
  5. "scripts": {
  6. "serve": "vue-cli-service serve",
  7. "build": "vue-cli-service build"
  8. },
  9. "dependencies": {
  10. "axios": "^0.19.2",
  11. "core-js": "^3.6.5",
  12. "vue": "^2.6.11",
  13. "vue-router": "^3.2.0"
  14. },
  15. "devDependencies": {
  16. "@vue/cli-plugin-babel": "^4.4.0",
  17. "@vue/cli-plugin-router": "^4.4.0",
  18. "@vue/cli-service": "^4.4.0",
  19. "vue-template-compiler": "^2.6.11"
  20. },
  21. "browserslist": [
  22. "> 1%",
  23. "last 2 versions",
  24. "not dead"
  25. ]
  26. }

1.4.vue.config.js而文件

  1. module.exports = {
  2. devServer:{
  3. port:8080,
  4. proxy: {
  5. '/juheNews':{
  6. target:'http://v.juhe.cn/', //需要跨域的url
  7. ws:true, //代理webSocket
  8. changeOrigin:true, //允许跨域
  9. pathRewrite:{
  10. '^/juheNews':'' //重写路径
  11. }
  12. }
  13. }
  14. }
  15. }

1.5.main.js文件

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import router from './router'
  4. import axios from 'axios'
  5. Vue.prototype.$axios = axios;
  6. Vue.config.productionTip = false
  7. new Vue({
  8. router,
  9. render: h => h(App)
  10. }).$mount('#app')

1.6.路由配置文件

  1. import Vue from 'vue'
  2. import VueRouter from 'vue-router'
  3. import TopNews from '../views/TopNews.vue'
  4. import TypeNews from '../views/TypeNews.vue'
  5. Vue.use(VueRouter)
  6. const routes = [{
  7. path: '/',
  8. name: 'Home',
  9. component: TopNews
  10. },{
  11. path: '/topNews',
  12. name: 'TopNews',
  13. component: TopNews
  14. },{
  15. path: '/typeNews',
  16. name: 'TypeNews',
  17. component: TypeNews
  18. }]
  19. const router = new VueRouter({
  20. routes
  21. })
  22. export default router

1.7.App.vue文件

  1. <template>
  2. <div id="app">
  3. <header>新闻头条</header>
  4. <nav>
  5. <ul>
  6. <li :class="{navinit:isActive=='topNews'}" @click="changeNav('topNews')">头条新闻</li>
  7. <li :class="{navinit:isActive=='typeNews'}" @click="changeNav('typeNews')">分类新闻</li>
  8. </ul>
  9. </nav>
  10. <router-view />
  11. </div>
  12. </template>
  13. <script>
  14. export default{
  15. data(){
  16. return {
  17. isActive:'typeNews'
  18. }
  19. },
  20. created() {
  21. let path = location.href;
  22. this.isActive = path.substring(path.lastIndexOf('/')+1);
  23. },
  24. methods:{
  25. changeNav(param){
  26. this.isActive = param;
  27. if(param=='topNews'){
  28. this.$router.push('/topNews');
  29. }else if(param=='typeNews'){
  30. this.$router.push('/typeNews');
  31. }
  32. }
  33. }
  34. }
  35. </script>
  36. <style>
  37. /******************** css reset ********************/
  38. html,body,div,header,nav,h1,h2,h3,h4,h5,h6,ul,li{
  39. margin: 0;
  40. padding: 0;
  41. font-family: "微软雅黑";
  42. }
  43. ul{
  44. list-style: none;
  45. }
  46. a{
  47. text-decoration: none;
  48. }
  49. header{
  50. width: 100%;
  51. height: 48px;
  52. background-color: #E03D3E;
  53. display: flex;
  54. justify-content: center;
  55. align-items: center;
  56. font-size: 20px;
  57. color: #fff;
  58. /*设置字间距*/
  59. letter-spacing: 4px;
  60. }
  61. nav{
  62. width: 100%;
  63. height: 56px;
  64. display: flex;
  65. justify-content: center;
  66. align-items: center;
  67. }
  68. nav ul{
  69. width: 160px;
  70. height: 26px;
  71. display: flex;
  72. justify-content: space-between;
  73. }
  74. nav ul li{
  75. width: 70px;
  76. height: 26px;
  77. display: flex;
  78. justify-content: center;
  79. align-items: center;
  80. }
  81. .navinit{
  82. color: #E03D3E;
  83. border-bottom: solid 2px #E03D3E;
  84. }
  85. </style>

1.8.NewsList.vue共通组件

<template>
    <div>
        <ul>
            <li v-for="item in data" @click="toNews(item.url)">
                <div class="img-box">
                    <img :src="item.thumbnail_pic_s">
                </div>
                <div class="text-box">
                    <h3>{{item.title | titleFilter}}</h3>
                                        <p>{{item.author_name}} {{item.date}}</p>
                </div>
            </li>
        </ul>
    </div>
</template>
<script>
    export default{
        props:['data'],
        methods:{
            toNews(url){
                location.href = url;
            }
        },
        filters:{
            titleFilter(value){
                if(value.length>24){
                    value=value.substr(0,24)+'...';
                }
                return value;
            }
        }
    }
</script>
<style scoped>
    ul{
        width: 100%;
    }
    ul li{
        box-sizing: border-box;
        padding: 6px;
        width: 100%;
        height: 93px;
        display: flex;
        border-bottom: dashed 1px #AAA;
        user-select: none;
        cursor: pointer;
    }
    ul li .img-box{
        flex: 0 0 100px;
        height: 80px;
    }
    ul li .img-box img{
        width: 100px;
        height: 80px;
    }
    ul li .text-box{
        flex: 1;
        box-sizing: border-box;
        padding-left: 10px;
    }
    ul li .text-box h3{
        font-size: 16px;
        font-weight: 300;
    }
    ul li .text-box p{
        font-size: 14px;
        text-align: right;
    }
</style>

1.9.TopNews.vue组件

<template>
    <div>
        <img src="../assets/logo.png">
        <NewsList :data="newsList"></NewsList>
    </div>
</template>
<script>
    import NewsList from '../components/NewsList'
    export default{
        data(){
            return {
                newsList:[]
            }
        },
        created() {
            this.$axios.get('/juheNews/toutiao/index',{
                params:{
                    type:'top',
                    key:'自己的key'
                }
            }).then(response=> {
                    this.newsList = response.data.result.data;
                })
                .catch(error=> {
                    console.log(error);
                });
        },
        components:{
            NewsList
        }
    }
</script>
<style scoped>
    img{
        width: 100%;
        height: 100px;
        display: block;
    }
</style>

1.10.TypeNews组件

<template>
    <div>
        <div class="news-img">
            <a :href="news.url">
                <img :src="news.thumbnail_pic_s">
            </a>
        </div>
        <div class="type-news">
            <ul>
                <li v-for="item in typeList" :class="{typeinit:isAlive==item.id}" @click="change(item.id)">
                    {{item.name}}
                </li>
            </ul>
        </div>
        <NewsList :data="newsList"></NewsList>
    </div>
</template>
<script>
    import NewsList from '../components/NewsList';
    export default{
        data(){
            return {
                typeList:[
                    {id:'shehui',name:'社会'},
                    {id:'guonei',name:'国内'},
                    {id:'guoji',name:'国际'},
                    {id:'yule',name:'娱乐'},
                    {id:'tiyu',name:'体育'},
                    {id:'junshi',name:'军事'},
                    {id:'keji',name:'科技'},
                    {id:'caijing',name:'财经'},
                    {id:'shishang',name:'时尚'}
                ],
                isAlive:'shehui',
                newsList:[],
                news:{}
            }
        },
        created() {
            this.getNews('shehui');
        },
        methods:{
            getNews(type){
                this.$axios.get('/juheNews/toutiao/index',{
                    params:{
                        type:type,
                        key:'自己的key'
                    }
                }).then(response=> {
                        this.newsList = response.data.result.data;
                        this.news = this.newsList[Math.floor(Math.random()*this.newsList.length)];
                    })
                    .catch(error=> {
                        console.log(error);
                    });
            },
            change(id){
                this.isAlive = id;
                this.getNews(id);
            }
        },
        components:{
            NewsList
        }
    }
</script>
<style scoped>
    .news-img img{
        width: 100%;
        height: 200px;
        display: block;
    }
    .type-news{
        width: 100%;
        margin-top: 8px;
    }
    .type-news ul{
        width: 100%;
        display: flex;
        justify-content: center;
        flex-wrap: wrap;
    }
    .type-news ul li{
        box-sizing: border-box;
        width: 48px;
        height: 22px;
        border: solid 1px #E03D3E;
        border-radius: 11px;
        margin: 5px 10px;
        font-size: 14px;
        color: #E03D3E;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    .typeinit{
        background-color: #E03D3E;
        color: #fff !important;     /*!important:将优先级提升最高*/
    }
</style>

[

](https://null_688_6639.gitee.io/javase/15Vue/09.%E7%AC%AC%E4%B9%9D%E7%AB%A0Vue%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.html)