1.cnode社区的基本构架
组件:
Header 头部
PostList 列表
Article 文章的详情页
SlideBar 侧边栏
UserInfo 用户个人信息
Pagination 分页组件
2.从零开始的实战
初始化项目
vue init webpack cnode
cnpm install
npm run dev
3. Header组件
引入组件
import Header from "./components/Header";
export default {
  name: "App",
  components: {
    Header
  }
};
在App.vue中插入组件
<Header></Header>
4. ProstList
API接口:https://cnodejs.org/api/v1/topics 获取帖子列表
拿到的参数分析
头像:author.avatar_url
回复量/浏览量 :reply_count/visit_count
帖子的标题:title
需要使用到过滤器:
时间:last_reply_at
帖子分类:top: 代表是否置顶
good: 代表是否精华
tab 是表示除了置顶和精华之外的其余分区
share 分享
ask 问答
job 招聘
引入Axios
npm install anxious
在main.js中引入Axios
import Axios from 'axios'
Vue.prototype.$http = Axios;
利用一个v-for循环来把参数放到dom节点上
<li v-for="post in posts">
          <!--头像-->
          <img :src="post.author.avatar_url" />
          <!--回复/浏览-->
          <span>
            <span class="reply_count">{{post.reply_count}}</span>
            /{{post.visit_count}}
          </span>
          <span
            :class="[{put_good:(post.good == true),put_top:(post.top == true),
            'topiclist-tab':(post.good != true && post.top !=true)}]"
          >
            <span>{{post| tabFormatter}}</span>
          </span>
          <!--标题-->
          <span>{{post.title}}</span>
          <!--时间-->
          <span class="last_reply">{{post.last_reply_at | formatDate}}</span>
        </li>
在main.js中添加过滤器,处理时间
Vue.filter('formatDate', function (str) {
  if (!str) return ""
  var date = new Date(str)
  var time = new Date().getTime() - date.getTime() //单位为毫秒,现在的时间-过去的时间
  if (time < 0) {
    return ""
  } else if ((time / 1000 < 30)) {
    return '刚刚'
  } else if ((time / 1000 < 60)) {
    return parseInt((time / 1000)) + '秒前'
  } else if ((time / 6000 < 60)) {
    return parseInt((time / 6000)) + '分钟前'
  } else if ((time / 3600000 < 24)) {
    return parseInt((time / 3600000)) + '小时前'
  } else if ((time / 86400000 < 31)) {
    return parseInt((time / 86400000)) + '天前'
  } else if ((time / 2592000000 < 12)) {
    return parseInt((time / 2592000000)) + '月前'
  } else {
    return parseInt((time / 31536000000)) + '年前'
  }
})
在main.js中添加过滤器处理小标题
Vue.filter('tabFormatter', function (post) {
  if (post.good == true) {
    return '精华'
  } else if (post.top == true) {
    return '置顶'
  } else if (post.tab == 'ask') {
    return '问答'
  } else if (post.tab == 'share') {
    return '分享'
  } else {
    return '招聘'
  }
})
5. Article
API https://cnodejs.org/api/v1/topic/ + 帖子ID
写入header
<div class="topic_header">
        <div class="topic_title">{{post.title}}</div>
        <ul>
          <li>·发布于: {{post.create_at |formatDate}}</li>
          <li>• 作者:{{post.author.loginname}}</li>
          <li>· {{post.visit_count}}次浏览</li>
          <li>· 来自{{post | tabFormatter}}</li>
        </ul>
        <div v-html="post.content" class="topic_content"></div>
      </div>
写入回复板块
<div>
        <div class="topbar">回复</div>
        <div v-for="(reply,index) in post.replies" class="replySec">
          <div class="replyUp">
            <router-link>
              <img src="reply.author.avatar_url" />
            </router-link>
            <router-link>
              <span>{{reply.author.loginname}}</span>
            </router-link>
            <span>☝{{index + 1}}楼</span>
            <span v-if="reply.ups.length>0">{{reply.ups.length}}</span>
          </div>
          <p v-html="reply.content"></p>
        </div>
      </div>
methods
利用axious调入api地址
methods: {
    getArticleData() {
      this.$http
        .get("https://cnodejs.org/api/v1/topic/" + this.$route.params.id)
        .then(res => {
          if (res.data.success == true) {
            this.post = res.data.data;
            this.isLoading = false;
          }
        })
        .catch(function(err) {
          console.log(err);
        });
    }
  },
在postlist上加入router-link
加入路由跳转
<router-link
            :to="{
            name: 'post_content',
            params: {
              id: post.id
            }
          }"
          >
            <span>{{post.title}}</span>
          </router-link>
在index.js加入router路由跳转
export default new Router({
  routes: [{
      name: 'root',
      path: '/',
      components: {
        main: PostList
      }
    },
    {
      name: 'post_content',
      path: '/topic/:id',
      components: {
        main: Article
      }
    }]
4.UserInfo
https://cnodejs.org/api/v1/user/
在article板块中加入router-link
 <router-link
              :to="{
                name:'user_info',
                params: {
                  name: reply.author.loginname
                }
              }"
            >
              <img :src="reply.author.avatar_url" alt />
            </router-link>
在index.js中添加路由
{
      name: 'user_info',
      path: '/userinfo/:name',
      components: {
        main: UserInfo
      }
    },
在回复板块上路由重新跳转回Postlist板块
<div class="replies">
        <p>回复的主题</p>
        <ul>
          <li v-for="item in userinfo.recent_replies" :key="item">
            <router-link
              :to="{
                    name: 'post_content',
                    params: {
                    id: item.id  
                    }
                }"
            >{{item.title}}</router-link>
          </li>
        </ul>
      </div>
在创建主题板块上也是同理
div class="topics">
        <p>创建的主题</p>
        <ul>
          <li v-for="item in userinfo.recent_topics" :key="item">
            <router-link
              :to="{
                    name: 'post_content',
                    params: {
                    id: item.id  
                    }
                }"
            >{{item.title}}</router-link>
          </li>
        </ul>
      </div>
    </div>
SlideBar注意事项
1.需要在PostList上多加上一个参数来显示作者名
<router-link
            :to="{
            name: 'post_content',
            params: {
              id: post.id,
              name: post.author.loginname
            }
          }"
          >
            <span>{{post.title}}</span>
          </router-link>
同理修改路由跳转
{
      name: 'post_content',
      path: '/topic/:id&author=:name',
      components: {
        main: Article,
        slidebar: SlideBar
      }
    },
2.处理回复的消息需要得到最近的五条,此时需要利用computed属性
<li v-for="list in topiclimitby5" :key="list">
          <router-link
            :to="{
            name: 'post_content',
            params: {
                id: list.id,
                name: list.author.loginname
            }
        }"
          >{{list.title}}</router-link>
        </li>
computed: {
    topiclimitby5() {
      if (this.userinfo.recent_topics) {
        return this.userinfo.recent_topics.slice(0, 5);
      }
    },
    replylimitby5() {
      if (this.userinfo.recent_replies) {
        return this.userinfo.recent_replies.slice(0, 5);
      }
    }
  },
3.由于点击连接主题路由跳转的地址相同,需要在Article组件中加入watch观察路由跳转
watch: {
    $route(to, from) {
      this.getArticleData();
    }
  }
6.Pagination注意事项
1.注意如何进行删除button和添加button
if (page == this.pagebtns[4]) {
        this.pagebtns.shift(); //移除第一个元素
        this.pagebtns.splice(4, 0, this.pagebtns[3] + 1); //添加最后一个
      } else if (page == this.pagebtns[0] && page != 1) {
        //现在第一个位置加一个
        this.pagebtns.unshift(this.pagebtns[0] - 1);
        //移除最后一个数字
        this.pagebtns.splice(5, 1);
      }
2.如何处理首页和下一页上一页的数据
if (typeof page != "number") {
        switch (page.target.innerText) {
          case "上一页":
            $("button.currentPage")
              .prev()
              .click();
            break;
          case "下一页":
            $("button.currentPage")
              .next()
              .click();
            break;
          case "首页":
            this.pagebtns = [1, 2, 3, 4, 5, "......"];
            this.changeBtn(1);
            break;
          default:
            break;
        }
        return;
      }
3.在Poslist中获得Pagination的参数
1.在组件添加方法
<pagination @handleList="renderList"></pagination>
2.方法
renderList(value) {
      this.postpage = value;
      this.getData();
    }
3.在pagination中传递数据
this.$emit("handleList", this.currentPage);