使用 vuejs 开发的一个面试页面

3,147 阅读3分钟
原文链接: www.icetower.cn

试题链接

参考答案GitHub地址

第一部分

是关于javascript的简答题,考的是js基础知识。涉及的内容包括数组操作,js中改变this指向的方法call()以及js原型法。

第二部分

使用SPA框架开发一个滚动加载的页面,我使用的是vue.js,涉及的开发知识比较多。项目核心知识包括Vue.js,webpack,vue-scroller,axios,moment.js,xml2json.js,跨域问题,JavaScript正则匹配。数据源是36kr.com/feed,数据格式是xml。

正文如下。大家可以看看试题,再看看我的参考答案,以下是详细介绍,欢迎大家给参考答案点一个star~

1.项目结构直接使用vue-scroller的演示demo 传送门

2.配置webpack,设置proxy代理,解决网络请求插件axios获取36kr.com/feed存在跨域问题。在webpack.config.js中devServer的设置添加proxy,如下:

devServer: {
    historyApiFallback: true,
    noInfo: true,
    proxy: {
        '/feed': {
        target: 'http://36kr.com/',
        changeOrigin: true,
        secure: false
      }
    }
  }

3.移动端使用相对长度单位rem,需要在index.html中添加一段js代码,根据屏幕尺寸设置根字体大小。

< script type="text/javascript">
        window.addEventListener('resize', infinite);
        function infinite() {
            const html = document.getElementsByTagName('html')[0];
            const htmlWidth = document.body.clientWidth
            if (htmlWidth >= 1080) {
                html.style.fontSize = "42px";
            } else {
                html.style.fontSize = (42/ 1080 * htmlWidth) + 'px';
            }
        }infinite();
  < /script>

4.这部分知识主要包括vue指令v-for、v-if、v-text、v-html。以及自定义事件refresh、infinite。css只要使用flex布局,比较简单不贴代码了,组件html结构如下:

< template>
  < div id="app">
    < scroller :on-refresh="refresh"
              :on-infinite="infinite"
              ref="my_scroller">
      < div v-for="(item, index) in items" class="row">
        < h1 class="itme-title" v-text="item.title.__cdata">
        < div class="itembox">
          < span class="author" v-text="item.author">
          < span class="category" v-text="item.category">
          < span class="timebox" v-text="newmoment(item.pubDate.__cdata)">< /span>
        < /div>
        < a class="item-content" :href="item.link">
          < div class="leftbox" v-html="handlerData(item.description.__cdata)">< /div>
          < div class="rightbox">
            < div class="imgbox">
              < img class="img" :src="skewImg.url?skewImg.url:'/src/assets/404.jpg'">
            < /div>
          < /div>
        < /a>
      < /div>
    < /scroller>
  < /div>
< /template>

5.在vue生命周期created阶段,通过axios发起网络请求,获取数据之后,将数据经过xml2json插件转换后,保存json数据到本地数组。

data() {
      return {
        items: [],//当前渲染数据
        allData: [],//所有数据
        dataLen: 0,//数据总长度
        step: 10,//上拉加载时,每次载入数据的数量
        times: 0,//上拉加载次数
        skewImg: []//缩略图保存地址
      }
    },
created() {
        var dataObj = {};
        var self = this;
        axios.get('/feed')
        .then(function (response) {
          var x2js = new X2JS();
          var dataObj = response.data;
          var jsonObj = x2js.xml_str2json( dataObj );
          var itemData = jsonObj.rss.channel.item;
          for (var i = itemData.length; i >= 0; i--) {
            self.allData.push(itemData[i])
          }
          self.dataLen = self.allData.length;
        })
        .catch(function (error) {
          console.log(error);
        });
    }

6.渲染到页面前数据处理,若当前item有多张图片,则保存第一张图片的src地址,若没有图片则保存一个空值。然后将数据去除所有html标签,只保留300个字符长度的文本,渲染到页面中:

handlerData(str) {
        var self = this;
        var dd = '';
        var arr = str.replace(/]*src=['"]([^'"]+)[^>]*>/i, function (match, capture) {
             dd = capture
        });
        self.skewImg['url'] = dd;
        var str = str.substring(0,300);
        return str.replace(/<[^>]+>/g,"");
      }

7.渲染到页面前,使用moment.js格式化时间。

newmoment(arg) {
        return moment(arg).format('MM 月 DD 日 hh:mm')
     }

8.上拉加载更多调用infinite()方法,每次上拉操作,次数times自加1,并往items数组添加step长度的数据:

infinite() {
        var self = this;
        setTimeout(() => {
          self.times +=1;
          var end = ((self.step)+1)*self.times;
          var sta  = end - self.step;
          self.items = self.items.concat(self.allData.slice(sta,end));//合并数组
          if (self.items.length >= self.dataLen) {//当加载完所有数据,禁用上拉加载
            this.$refs.my_scroller.finishInfinite(true)
          }
          setTimeout(() => {
            this.$refs.my_scroller.finishInfinite(true)
          })
        }, 1500)
      },

9.下拉刷新调用reflesh()方法,重新发起一次网络请求,并且往items中填充step条数据:

refresh() {
        setTimeout(() => {
        var dataObj = {};
        var self = this;
        axios.get('/feed')
        .then(function (response) {
          var x2js = new X2JS();
          var dataObj = response.data;
          var jsonObj = x2js.xml_str2json( dataObj );
          var itemData = jsonObj.rss.channel.item;
          for (var i = itemData.length; i >= 0; i--) {
            self.allData.push(itemData[i])
          }
          self.items = self.allData.slice(sta,end);
          var end = ((self.step)+1)*self.times;
          var sta  = end - self.step;
        })
        .catch(function (error) {
          console.log(error);
        });
          if (this.$refs.my_scroller)
            this.$refs.my_scroller.finishPullToRefresh();
        }, 1500)
      },

最后是遗留问题:应该是webpack配置有点问题,打包之后,不知道是否是路径问题,设置的proxy代理失效。求大神帮忙看看。