VUE实战-知乎日报(3) 应用组件源码分析

使用click绑定事件,当每日推荐和主题日报被点击时,绑定类名on,在此文件中是出现蓝色标记当前开大的菜单.

:class="{on:type==='recommend}"当前dom的type为recommend时,绑定类名on,主题日报同理。

 handleToRecommend () {
                this.type = 'recommend';
                this.recommendList = [];
                this.dailyTime = $.getTodayTime();
                this.getRecommendList();
            },
            handleToTheme (id) {
                this.type = 'daily';
                this.themeId = id;
                this.list = [];
                $.ajax.get('theme/' + id).then(res => {
                    this.list = res.stories
                        .filter(item => item.type !== 1);
                })
            }通过点击事件,触发函数修改type值,从而给子菜单添加on类名;

在data中,type默认为recommend,故应用开启时,每日推荐出现标记.。

 对应CSS{

.daily-menu ul li a:hover, .daily-menu ul li a.on{

color: #3399ff;

}

};

 <div class="daily-menu-item"
                 :class="{ on: type === 'daily' }"
                 @click="showThemes = !showThemes">主题日报</div>
            <ul v-show="showThemes">
                <li v-for="item in themes" :key="item.id">
                    <a
                        :class="{ on: item.id === themeId && type === 'daily' }"
                        @click="handleToTheme(item.id)">{{ item.name }}</a>
                </li>
            </ul>

主题日报菜单通过click修改showThemes布尔值,达到隐藏、显示themes列表;v-show="showThemes"当showThemes为真显示,showThemes为假时隐藏;

v-for="item in themes" :key="item.id";key 的特殊属性主要用在 Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes。如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用key,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。

key 的作用渲染时候的参照关键字,或者渲染的顺序; //个人意见保留

通过formatDay格式化日期,之后通过日期分块,再根据对应日期渲染。

注意:

1,给vue组件绑定事件时候,必须加上native ,不然不会生效(监听根元素的原生事件,使用 .native 修饰符)

2,等同于在自组件中:

   子组件内部处理click事件然后向外发送click事件:$emit("click".fn)

即在template 或在组件中引用组件,组件会拦截click,需要加上native原生触发。

 <template v-if="type === 'daily'">
                <Item
                    v-for="item in list"
                    :data="item"
                    :key="item.id"
                    @click.native="handleClick(item.id)"></Item>
            </template>
<script>
 handleClick (id) {
                this.articleId = id;
            }
</script>

此处组件对应主题日报;

踩坑。

提一下v-if和v-show的区别: v-if 当值为 true时,显示div ,当值为false时,改元素消失,代码也会消失,相当于将代码删除了,当在为true时,页面会重新渲染div; 
而v-show 控制的隐藏出现,只是将css属性设为了display:none 或block;

v-if修改会重新渲染,v-show不会。

app.vue:

<template>
    <div class="daily">
        <div class="daily-menu">
            <div class="daily-menu-item"
                 @click="handleToRecommend"
                 :class="{ on: type === 'recommend' }">每日推荐</div>
            <div class="daily-menu-item"
                 :class="{ on: type === 'daily' }"
                 @click="showThemes = !showThemes">主题日报</div>
            <ul v-show="showThemes">
                <li v-for="item in themes" :key="item.id">
                    <a
                        :class="{ on: item.id === themeId && type === 'daily' }"
                        @click="handleToTheme(item.id)">{{ item.name }}</a>
                </li>
            </ul>
        </div>
        <div class="daily-list" ref="list">
            <template v-if="type === 'recommend'">
                <div v-for="list in recommendList" :key="formatDay(list.date)">
                    <div class="daily-date">{{ formatDay(list.date) }}</div>
                    <Item
                        v-for="item in list.stories"
                        :data="item"
                        :key="item.id"
                        @click.native="handleClick(item.id)"></Item>
                </div>
            </template>
            <template v-if="type === 'daily'">
                <Item
                    v-for="item in list"
                    :data="item"
                    :key="item.id"
                    @click.native="handleClick(item.id)"></Item>
            </template>
        </div>
        <daily-article :id="articleId"></daily-article>
    </div>
</template>
<script>
    import Item from './components/item.vue';
    import dailyArticle from './components/daily-article.vue';
    import $ from './libs/util';

    export default {
        components: { Item, dailyArticle },
        data () {
            return {
                themes: [],
                showThemes: false,
                type: 'recommend',
                recommendList: [],
                dailyTime: $.getTodayTime(),
                list: [],
                themeId: 0,
                articleId: 0,
                isLoading: false
            }
        },
        methods: {
            handleToRecommend () {
                this.type = 'recommend';
                this.recommendList = [];
                this.dailyTime = $.getTodayTime();
                this.getRecommendList();
            },
            handleToTheme (id) {
                this.type = 'daily';
                this.themeId = id;
                this.list = [];
                $.ajax.get('theme/' + id).then(res => {
                    this.list = res.stories
                        .filter(item => item.type !== 1);
                })
            },
            getThemes () {
                $.ajax.get('themes').then(res => {
                    this.themes = res.others;
                })
            },
            getRecommendList () {
                this.isLoading = true;
                const prevDay = $.prevDay(this.dailyTime + 86400000);
                $.ajax.get('news/before/' + prevDay).then(res => {
                    this.recommendList.push(res);
                    this.isLoading = false;
                })
            },
            formatDay (date) {
                let month = date.substr(4, 2);
                let day = date.substr(6, 2);
                if (month.substr(0, 1) === '0') month = month.substr(1, 1);
                if (day.substr(0, 1) === '0') day = day.substr(1, 1);
                return `${month} 月 ${day} 日`;
            },
            handleClick (id) {
                this.articleId = id;
            }
        },
        mounted () {
            this.getRecommendList();
            this.getThemes();
            const $list = this.$refs.list;
            $list.addEventListener('scroll', () => {
                if (this.type === 'daily' || this.isLoading) return;
                if
                (
                    $list.scrollTop
                    + document.body.clientHeight
                    >= $list.scrollHeight
                )
                {
                    this.dailyTime -= 86400000;
                    this.getRecommendList();
                }
            });
        }
    }
</script>

猜你喜欢

转载自blog.csdn.net/qq_34067556/article/details/81871916