1.搭建项目
1.1通过vue-cli脚手架搭建项目:vue create toutiao
(选择 vuex/eslint(standard)/pre-cssprocesser(less))
1.2在main.js中引入样式:import ‘./style/index.css’
1.3拷贝图片资源到assets目录下
1.4在App.vue中拷贝基本结构:
<div id="app"> <ul class="catagtory"> <li class='select'>开发者资讯</li> <li>ios</li> <li>c++</li> <li>android</li> <li>css</li> <li>数据库</li> <li>区块链</li> <li>go</li> <li>产品</li> <li>后端</li> <li>linux</li> <li>人工智能</li> <li>php</li> <li>javascript</li> <li>架构</li> <li>前端</li> <li>python</li> <li>java</li> <li>算法</li> <li>面试</li> <li>科技动态</li> <li>js</li> <li>设计</li> <li>数码产品</li> <li>html</li> <li>软件测试</li> <li>测试开发</li> </ul> <div class="list"> <div class="article_item"> <h3 class="van-ellipsis">python数据预处理 :数据标准化</h3> <div class="img_box"> <img src="@/assets/back.jpg" class="w100" /> </div> <!----> <div class="info_box"> <span>13552285417</span> <span>0评论</span> <span>2018-11-29T17:02:09</span> </div> </div> </div> </div>
2.封装分类组件和频道组件
components/catagtory.vue 和 components/new-list.vue
3.在vuex中加载分类和频道数据
3.1设计categtory和newlist的vuex模块
采用模块化的管理模式,建立一个专门的模块来管理分类和新闻数据
3.1.1安装请求数据工具axios
3.1.2在store目录下新建目录modules,新建categtory.js和newlist.js,模块结构:
namespaced: true, //子模块加锁
export default { namespaced: true, state: {}, mutations: {}, actions: {} }
在store/index.js中引入定义的两个(子)模块:
import catagtory from './modules/catagtory' import newlist from './modules/newlist' export default new Vuex.Store({ state: { }, mutations: { }, actions: { }, modules: { catagtory, newlist } })
3.2分类模块下设置分类数组和当前激活分类
3.2.1在catagtory的 state中定义分类频道列表和当前激活
state: { catagtory: [], currentCatagtory: '' }
3.2.2定义更新频道列表的mutations
此处载荷即要更新的数组
mutations: { updateCatagtory (state, payload) { state.catagtory = payload // 更新分类数据 }, updateCurrentCatagtory (state, payload) { state.currentCatagtory = payload } }
3.2.3通过getters建立对于分类数据和当前分类的快捷访问(最外层!!)
在store/index.js中建立对子模块的快捷访问:
export default new Vuex.Store({ state: { }, mutations: { }, actions: { }, modules: { catagtory, newlist }, getters: { catagtory: state => state.catagtory.catagtory, // 建立快捷访问 currentCatagtory: state => state.catagtory.currentCatagtory } })
3.3遍历分类数据并判断激活class
分类组件(catagtory.vue)遍历vuex数据
此处用动态class为select设置动态值以达到高亮的效果:
:class="{ select: currentCatagtory === item.id }"
<ul class="catagtory"> <li :class="{ select: currentCatagtory === item.id }" v-for="item in catagtory" :key="item.id">{{ item.name }}</li>
import { mapGetters } from 'vuex' computed: { ...mapGetters(['catagtory', 'currentCatagtroy']) },
3.4封装调用获取分类action,默认激活第一个分类
3.4.1定义获取频道列表的action, 将第一个频道激活
利用了对象解构!!
const { data: { data: { channels } } } =
await axios.get('http://ttapi.research.itcast.cn/app/v1_0/channels')
actions: { async getCatagtory (context) { // promise // async/await // axios 默认包了一层data的数据结构 const { data: { data: { channels } } } = await axios.get('http://ttapi.research.itcast.cn/app/v1_0/channels') // 需要通过mutation才能修改state context.commit('updateCatagtory', channels) // 更新数组 context.commit('updateCurrentCatagtory', channels[0].id) // 更新当前激活id } }
3.4.2初始化catagtory时调用action
import { mapGetters } from 'vuex' export default { computed: { ...mapGetters(['catagtory']) }, created () { //调用子模块actions(加锁) this.$store.dispatch('catagtory/getCatagtory') } }
3.4.3点击分类时,触发分类切换
<li @click="$store.commit('catagtory/updateCurrentCatagtory', item.id)" :class="{ select: currentCatagtroy === item.id }" v-for="item in catagtory" :key="item.id">{{ item.name }}</li>
3.5 定义新闻数据,并封装获取新闻的Action
3.5.1在newlist.js中定义获取头条内容的数据
state: { allData: {} // 放置的是所有的数据 { 分类id: 列表1, 分类id:列表2 } }
(****)3.5.2定义更新头条内容的mutations
载荷 { currentCatagtory, list } 如 { 1: [], 2: [], 3: []}
浅拷贝:state.allData = { ...state.allData, [currentCatagtory]: list }
mutations: { // payload 载荷 { 1: [], 2: [], 3: [], 4} updateList (state, { currentCatagtory, list }) { // 不是响应式的 // state.allData[currentCatagtory] = list // 这样做事大错特错第 感觉不到变化 就不会通知组件 state.allData = { ...state.allData, [currentCatagtory]: list } // 这句代码的含义 就相当于 在一个新的对象后面追加了一个属性 更新某个属性的内容 } },
3.5.3定义根据分类标识获取新闻的action
actions: { // 获取新闻列表数据 // 分类id只能通过传递的方式传进来 async getNewList (context, cataId) { const { data: { data: { results } } } = await axios.get(`http://ttapi.research.itcast.cn/app/v1_1/articles?channel_id=${cataId}×tamp=${Date.now()}&with_top=1`) // results是新闻列表 context.commit('updateList', { currentCatagtory: cataId, list: results }) } }
3.6监听激活分类,触发获取新闻Action
在new-list组件中,引入当前分类的id,监视其改变,一旦改变,触发获取新闻的action
import { mapGetters } from 'vuex' export default { computed: { ...mapGetters(['currentCatagtroy']) }, watch: { currentCatagtory (newValue) { this.$store.dispatch('newlist/getNewList', newValue) } } }
3.7处理显示新闻内容的数据
3.7.1定义当前显示列表的getters
getters: { currentList: state => state.newlist.allData[state.catagtory.currentCatagtory] || [] }
3.7.2修改new-list内容
<template> <div class="list"> <div class="article_item" v-for="item in currentList" :key="item.art_id"> <h3 class="van-ellipsis">{{ item.title }}</h3> <div class="img_box" v-if="item.cover.type === 1"> <img :src="item.cover.images[0]" class="w100" /> </div> <div class="img_box" v-else-if="item.cover.type === 3"> <img :src="item.cover.images[0]" class="w33" /> <img :src="item.cover.images[1]" class="w33" /> <img :src="item.cover.images[2]" class="w33" /> </div> <!----> <div class="info_box"> <span>{{ item.aut_name }}</span> <span>{{ item.comm_count }}评论</span> <span>{{ item.pubdate }}</span> </div> </div> </div> </template> <script> // 引入当前激活的分类id import { mapGetters } from 'vuex' export default { computed: { ...mapGetters(['currentCatagtory', 'currentList']) }, watch: { currentCatagtory (newValue) { // newValue是当前最新的激活的id this.$store.dispatch('newlist/getNewList', newValue) } } } </script> <style> </style>