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共通组件

  1. <template>
  2. <div>
  3. <ul>
  4. <li v-for="item in data" @click="toNews(item.url)">
  5. <div class="img-box">
  6. <img :src="item.thumbnail_pic_s">
  7. </div>
  8. <div class="text-box">
  9. <h3>{{item.title | titleFilter}}</h3>
  10. <p>{{item.author_name}} {{item.date}}</p>
  11. </div>
  12. </li>
  13. </ul>
  14. </div>
  15. </template>
  16. <script>
  17. export default{
  18. props:['data'],
  19. methods:{
  20. toNews(url){
  21. location.href = url;
  22. }
  23. },
  24. filters:{
  25. titleFilter(value){
  26. if(value.length>24){
  27. value=value.substr(0,24)+'...';
  28. }
  29. return value;
  30. }
  31. }
  32. }
  33. </script>
  34. <style scoped>
  35. ul{
  36. width: 100%;
  37. }
  38. ul li{
  39. box-sizing: border-box;
  40. padding: 6px;
  41. width: 100%;
  42. height: 93px;
  43. display: flex;
  44. border-bottom: dashed 1px #AAA;
  45. user-select: none;
  46. cursor: pointer;
  47. }
  48. ul li .img-box{
  49. flex: 0 0 100px;
  50. height: 80px;
  51. }
  52. ul li .img-box img{
  53. width: 100px;
  54. height: 80px;
  55. }
  56. ul li .text-box{
  57. flex: 1;
  58. box-sizing: border-box;
  59. padding-left: 10px;
  60. }
  61. ul li .text-box h3{
  62. font-size: 16px;
  63. font-weight: 300;
  64. }
  65. ul li .text-box p{
  66. font-size: 14px;
  67. text-align: right;
  68. }
  69. </style>

1.9.TopNews.vue组件

  1. <template>
  2. <div>
  3. <img src="../assets/logo.png">
  4. <NewsList :data="newsList"></NewsList>
  5. </div>
  6. </template>
  7. <script>
  8. import NewsList from '../components/NewsList'
  9. export default{
  10. data(){
  11. return {
  12. newsList:[]
  13. }
  14. },
  15. created() {
  16. this.$axios.get('/juheNews/toutiao/index',{
  17. params:{
  18. type:'top',
  19. key:'自己的key'
  20. }
  21. }).then(response=> {
  22. this.newsList = response.data.result.data;
  23. })
  24. .catch(error=> {
  25. console.log(error);
  26. });
  27. },
  28. components:{
  29. NewsList
  30. }
  31. }
  32. </script>
  33. <style scoped>
  34. img{
  35. width: 100%;
  36. height: 100px;
  37. display: block;
  38. }
  39. </style>

1.10.TypeNews组件

  1. <template>
  2. <div>
  3. <div class="news-img">
  4. <a :href="news.url">
  5. <img :src="news.thumbnail_pic_s">
  6. </a>
  7. </div>
  8. <div class="type-news">
  9. <ul>
  10. <li v-for="item in typeList" :class="{typeinit:isAlive==item.id}" @click="change(item.id)">
  11. {{item.name}}
  12. </li>
  13. </ul>
  14. </div>
  15. <NewsList :data="newsList"></NewsList>
  16. </div>
  17. </template>
  18. <script>
  19. import NewsList from '../components/NewsList';
  20. export default{
  21. data(){
  22. return {
  23. typeList:[
  24. {id:'shehui',name:'社会'},
  25. {id:'guonei',name:'国内'},
  26. {id:'guoji',name:'国际'},
  27. {id:'yule',name:'娱乐'},
  28. {id:'tiyu',name:'体育'},
  29. {id:'junshi',name:'军事'},
  30. {id:'keji',name:'科技'},
  31. {id:'caijing',name:'财经'},
  32. {id:'shishang',name:'时尚'}
  33. ],
  34. isAlive:'shehui',
  35. newsList:[],
  36. news:{}
  37. }
  38. },
  39. created() {
  40. this.getNews('shehui');
  41. },
  42. methods:{
  43. getNews(type){
  44. this.$axios.get('/juheNews/toutiao/index',{
  45. params:{
  46. type:type,
  47. key:'自己的key'
  48. }
  49. }).then(response=> {
  50. this.newsList = response.data.result.data;
  51. this.news = this.newsList[Math.floor(Math.random()*this.newsList.length)];
  52. })
  53. .catch(error=> {
  54. console.log(error);
  55. });
  56. },
  57. change(id){
  58. this.isAlive = id;
  59. this.getNews(id);
  60. }
  61. },
  62. components:{
  63. NewsList
  64. }
  65. }
  66. </script>
  67. <style scoped>
  68. .news-img img{
  69. width: 100%;
  70. height: 200px;
  71. display: block;
  72. }
  73. .type-news{
  74. width: 100%;
  75. margin-top: 8px;
  76. }
  77. .type-news ul{
  78. width: 100%;
  79. display: flex;
  80. justify-content: center;
  81. flex-wrap: wrap;
  82. }
  83. .type-news ul li{
  84. box-sizing: border-box;
  85. width: 48px;
  86. height: 22px;
  87. border: solid 1px #E03D3E;
  88. border-radius: 11px;
  89. margin: 5px 10px;
  90. font-size: 14px;
  91. color: #E03D3E;
  92. display: flex;
  93. justify-content: center;
  94. align-items: center;
  95. }
  96. .typeinit{
  97. background-color: #E03D3E;
  98. color: #fff !important; /*!important:将优先级提升最高*/
  99. }
  100. </style>