一、移动端项目的建立
新建一个项目---->在src/components目录路径下新建一个common文件夹 用于存放多次复用的组件 再新建一个page文件夹 用于存放页面组件----->在page文件夹中新建home.vue---->在router/index.js中写path路径让“/”时切换到home页面
在src下新建一个style文件夹用于存放css 引用这个css的方法是:在CMD中按装 cnpm i node-sass sass-loader --save-dev (非常容易丢包 造成不能在style中用@import方法引入 所以需要在script中用import “路径”的方法映入css文件 在style中直接定义变量并使用),注意用rem做单位
二、 sass与scss的区别:
scss是sass的升级版 可以使用花括号{ }进行嵌套,还新增了简单的计算功能等。。。。。
在home.vue中引用css
<style lang="scss"> // 在scss中是$定义变量 lang=“scss” 用于识别scss语法
$c:red
div{
color:$c
}
</style>
在scss中倒入样式文件 @import(空格)"文件路径" 不特指css文件 也可以倒入scss文件
在style中新建reset.css 用于设置公共样式 并利用@import将其引入home.vue
在style中新建var.css 用于通过变量设置样式 并利用@import将其引入home.vue 这样就可以在引用变量设置样式 $sc:25
在index.html中的script中设置根元素的font-size
index.html
<script>
document.documentElement.style.fontSize = document.documentElement.clientWidth/15+'px'; //documentElement 代表的是dom元素也就是根元素
</script>
375/15=25 所以设置$sc为25
在home.vue中的template中写<header> <footer> <rooter-view/>------->在style中写scss样式 ----->在page文件夹中新建home.vue中包含的各种组件----->在router/index.js中引入需要的组件 并且设定路由
三、引入iconfont的方法:
iconfont 官网 搜索需要的icon ----->加入购物车---->添加到对应的项目----->复制对应的连接在index.html中用外链的方式引入(每次引入新的icon需要更新连接)----->在对应的<i>标签中加入icon码。
![](https://i-blog.csdnimg.cn/blog_migrate/c4803f62f43b786fb848e613596bb12a.png)
<link rel="stylesheet" type="text/css" href="//
at.alicdn.com/t/font_944598_uq9lb6npz0h.css"/>
![](https://i-blog.csdnimg.cn/blog_migrate/a4cb957eb3a54988e5471469cd1e558c.png)
http://fontawesome.dashgame.com/ fontawesome icon资源库 不好用
完整代码 11.30随堂总结/p3
index.html
<link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_944598_oozhva7wh9.css"/> <!--引入iconfont-->
<script>
document.documentElement.style.fontSize = document.documentElement.clientWidth/15 + 'px'; //设置dom的字体大小
</script>
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import VueJsonp from 'vue-jsonp'
import MintUI from 'mint-ui'
import 'mint-ui/lib/style.css'
Vue.use(MintUI)
Vue.use(VueJsonp)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
components/page/home.vue
<template>
<div>
<header>
<i class='iconfont left'></i>
<router-link to="/search"><i class='iconfont right'></i></router-link>
<div id="nav" class="nav"> <!--导航栏 -->
<div id="leftnav" class="leftnav">
<div class="swiper-container2 " >
<div class="swiper-wrapper w">
<div class="swiper-slide" v-for="(item,index) in title"v-bind:class="{'active':curIndex===index}">
{{item.text}} <!--循环标题遍历导航栏-->
</div>
</div>
</div>
</div>
<div><i class="iconfont t"></i></div>
</div>
</header>
<router-view class="content"/><!--这里面装的是子组件,通过router-link改变子组件变换中间部分的内容-->
<footer>
<ul>
<li><router-link to="/home/index"><i class='iconfont logo'></i>首页</router-link></li>
<li><router-link to="/home/video"><i class='iconfont logo'></i>视频</router-link></li>
<li><router-link to="/home/subscribe"><i class='iconfont logo'></i>订阅</router-link></li>
<li><router-link to="/users"><i class='iconfont logo'></i>个人</router-link></li>
</ul>
</footer>
</div>
</template>
<script>
import '@/style/reset.css'
import axios from 'axios'
import Swiper from 'swiper'
import '../../../node_modules/swiper/dist/css/swiper.css'
export default{
data(){
return{
news:[],//这是从接口中请求的所有数据都存放在这里面
curIndex:0,
title:[
{
text:'头条',
type:'index'
},
{
text:'娱乐',
type:'pcent'
},
{
text:'科技',
type:'pctech'
},
{
text:'体育',
type:'yl'
},
{
text:'财经',
type:'yl'
},
{
text:'军事',
type:'yl'
},
{
text:'音乐',
type:'yl'
},
{
text:'热点',
type:'yl'
},
{
text:'视频',
type:'yl'
},
{
text:'奇趣',
type:'yl'
},
{
text:'图片',
type:'yl'
},
{
text:'电影',
type:'yl'
},
{
text:'历史',
type:'yl'
},
{
text:'内地',
type:'yl'
},
{
text:'国际',
type:'yl'
}
]
}
},
mounted(){
var vm = this //1)为当前的this是swiper对象 所以要指定一个vm来初始化this
new Swiper(".swiper-container2",{ //导航栏实例化swiper 让导航栏可以滑动
freeMode:true,
slidesPerView:"auto",
on:{ //on是事件处理函数
click(){
//alert(this.clickedIndex) //swiper上的属性可以看到当前点击的下标
//console.log(this) //是Swiper对象,里面包含了许多属性
//console.log(this.wrapperEl.clientWidth) //这样可以获取到包裹所有元素的那个容器的宽度
vm.curIndex=this.clickedIndex // 2)
var el = this.slides[this.clickedIndex] //获取当前点击的那个元素
var elpos=el.offsetLeft+el.clientWidth/2 ; //当前点击元素的位置 el.clientWidth/2 是当前元素的中心点
var swiperwrapperWidth=this.wrapperEl.clientWidth //导航栏包裹部分的宽度
var maxDis=this.maxTranslate() //滚动的最大距离
var maxPos=-maxDis+swiperwrapperWidth/2 ;//最大的中心位置
//console.log(maxDis,swiperwrapper,elpos)
if(elpos<swiperwrapperWidth/2){ //如果元素当前位置小于容器宽度的一半那么就让它回归到0
this.setTranslate(0)
}else if(elpos>maxPos){
this.setTranslate(maxDis)
}else{
this.setTranslate(swiperwrapperWidth/2-elpos)
}
this.setTransition(500) //设置滑动时间
if(vm.curIndex===0){
vm.$router.push({'name':'index'})
}else{
vm.$router.push('/home/'+vm.title[vm.curIndex].type)
}
}
}
})
},
}
</script>
<style lang="scss" >
$sc:25;
header{
width:100%;
height:75/$sc+rem;
background: #fff;
position: fixed;
top:0;
left:0;
.left{
float:left;
margin-left: 10/$sc+rem;
margin-top: 10/$sc+rem;
}
.right{
float:right;
margin-right: 20/$sc+rem;
margin-top: 10/$sc+rem;
}
}
#nav{
display:flex;
width: 100%;
height:37.5/$sc+rem;
line-height:37.5/$sc+rem;
}
.leftnav{
width:90%;
overflow: hidden;
}
.t{
margin-left: 5/$sc+rem;
font-size:17/$sc+rem
}
.w div{
width:50/$sc+rem;
text-align: center;
font-size:17/$sc+rem
}
.active{
color:yellowgreen;
border-bottom: 6/$sc+rem solid yellowgreen;
}
.content{
position:absolute;
top:75/$sc+rem;
left: 0;
bottom: 49/$sc+rem;
right: 0;
background:#fff;
overflow-y: auto;
}
footer{
width: 100%;
background:#fff;
position:absolute;
bottom: 0;
left: 0;
ul{
display: flex;
li{
flex: 1;
text-align: center;
height:49/$sc+rem;
a{
color: #000;
display:inline-block ;
margin-top:0.4rem ;
font-size:14/$sc+rem;
.logo{
display: block;
font-size:14/$sc+rem;
}
}
}
}
}
</style>
src/style/reset.css
body,ol,ul,h1,h2,h3,h4,h5,h6,p,th,td,dl,dd,form,fieldset,legend,input,textarea,select{margin:0;padding:0}
body{font:12px "宋体","Arial Narrow",HELVETICA;background:#fff;}
a{text-decoration:none}
a:hover{text-decoration:underline}
em{font-style:normal}
li{list-style:none}
img{border:0;vertical-align:middle}
table{border-collapse:collapse;border-spacing:0}
p{word-wrap:break-word}
.noborder{border:0;}
.left{float:left;}
.right{float:right;}
congif/index.js
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
"/wz":{
target:"http://cre.mix.sina.com.cn",
changeOrigin:true,
pathRewrite:{
"^/wz":"/"
}
}
},
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Home from '@/components/page/Home'
import Index from '@/components/page/index'
import Video from '@/components/page/video'
import Subscribe from '@/components/page/subscribe'
import Users from '@/components/page/users'
import Search from '@/components/page/search'
import Typenews from '@/components/page/typenews'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect:{name:'home'}
},
{
path:'/home',
name:'home',
component:Home,
redirect:{name:'index'},
children:[
{
path:'/home/index',
name:'index',
component:Index,
},
{
path:'/home/video',
name:'video',
component:Video
},
{
path:'/home/subscribe',
name:'subscribe',
component:Subscribe
},
{
path:'/home/:type',
name:'typenews',
component:Typenews
},
]
},
{
path:'/users',
name:'users',
component:Users
},
{
path:'/search',
name:'search',
component:Search
}
]
})
components/page/subscribe
<template>
<div>这里是订阅页面</div>
</template>
<script>
</script>
<style>
</style>
components/page/video
<template>
<div>这里是视频页面</div>
</template>
<script>
</script>
<style scoped>
.content{
background:#fa34c5
}
</style>
components/page/video
<template>
<div>这里是个人中心
<footer>
<ul>
<li><router-link to="/home/index"><i class='iconfont logo'></i>首页</router-link></li>
<li><router-link to="/home/video"><i class='iconfont logo'></i>视频</router-link></li>
<li><router-link to="/home/subscribe"><i class='iconfont logo'></i>订阅</router-link></li>
<li><router-link to="/users"><i class='iconfont logo'></i>个人</router-link></li>
</ul>
</footer>
</div>
</template>
<script>
</script>
<style lang="scss"scoped>
$sc:25;
footer{
width: 100%;
background:#ddcc88;
position:absolute;
bottom: 0;
left: 0;
ul{
display: flex;
li{
flex: 1;
text-align: center;
height:49/$sc+rem;
a{
color: #777;
display:inline-block ;
margin-top:0.4rem ;
.logo{
display: block;
}
}
}
}
}
</style>
components/page/search
<template>
<div>
<header>
<router-link to="/home/index"><i class='iconfont left'></i></router-link>
<div class="searchpart"><input type="text" id="txt" class="blur" placeholder="搜索文章、视频、订阅号"></div>
<router-link to="/home/index" class="right1">取消</router-link>
</header>
</div>
</template>
<script>
</script>
<style lang='scss' scoped>
$sc:25;
header{
width:100%;
height:44/$sc+rem;
background: #aa3344;
position: fixed;
top:0;
left:0;
.left{
float:left;
margin-left: 10/$sc+rem;
margin-top: 10/$sc+rem;
}
.right1{
position: absolute;
top:10/$sc+rem;
right: 10/$sc+rem;
font-size: 16/$sc+rem;
}
.searchpart{
width:253/$sc+rem;
height:23/$sc+rem;
border:1px solid #333;
border-radius:0.6rem;
position: relative;
margin:10/$sc+rem auto;
#txt{
position: absolute;
top: 0.16rem;
left: 0.4rem;
font-size: 0.5rem;
width:8.4rem;
outline: none;
border: none;
}
}
}
</style>
components/page/index.vue 这是首页上的轮播图和数据
<template>
<div>
<div class="swiper-container"> <!--轮播图-->
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="item in news">
<img v-bind:src='item.thumb'>
</div>
</div>
<!--新闻列表-->
<ul v-infinite-scroll="loadMore"
infinite-scroll-disabled="loading"
infinite-scroll-distance="10"> <!--当与下方距离10以内的时候触发loadmore 第二个是无限滚动是否关闭,靠布尔值决定-->
<li v-for="item in list" class="newspart">
<div>
<h3>{{item.title}}</h3>
<p class="sor">{{item.source}}</p>
</div>
<div>
<img v-bind:src="item.picInfo[0].url">
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
import { Toast } from 'mint-ui';
import axios from 'axios'
import Swiper from 'swiper'
import '../../../node_modules/swiper/dist/css/swiper.css'
export default{
data(){
return{
news:[],//这是从接口中请求的所有数据都存放在这里面
list:[],
start:0,
end:9,
arr:['A','B01','B02','B03','B04','B05','B10'],
page:0,
loading:false //false可以发请求,true不能发请求
}
},
created(){ //从接口中请求数据
axios.get("/wz/api/v3/get?_=1543659415163").then((res)=>{
this.news=res.data.data.filter((item,index)=>{
return index<4 //返回前四条数据
})
})
/*this.$jsonp("http://temp.163.com/special/00804KV1/post1603_api_all.js?_=1543659415162",{
callbackName:"callback"
}).then((res)=>{ //这是一次性将所有的数据都请求到
this.list=res.data.filter((item,index)=>{
return index<10 && item.pic[0]
})
console.log(res)
})*/
this.getData()
},
methods:{
loadMore(){ //发送继续加载数据的请求
this.getData()
console.log("loadMore")
},
getData(){
if(this.page===this.arr.length-1){
Toast({
message: '正在加载', //弹框中的内容
position: 'bottom',
duration: 1500
});
return
}
this.loading=true //别的请求无法发送,保证同一时刻只能发一个请求
/* var tk = Toast({
iconClass:'fa fa-spinner fa-pulse', //这是iconawesome图标库中的动态图标
position:'middle',
duration:-1
})*/
this.$jsonp(`http://3g.163.com/touch/jsonp/sy/recommend/${this.start}-${this.end}.html`
,{ //数据不能写死所以需要用字符串拼接
miss:"00",
refresh:this.arr[this.page]
}).then((res)=>{ //这是一次性将所有的数据都请求到
this.list=this.list.concat(res.list.filter((item)=>{
return item.picInfo[0] && !item.adddata
}))
console.log(res)
this.loading=false;
this.page++;
this.start=this.start+10;
this.end=this.start+9;
/*tk.close() //把loading框关闭*/
})
}
},
watch:{
news(){
this.$nextTick(()=>{
var mySwiper = new Swiper ('.swiper-container', {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
autoplay: {
delay: 3000,
stopOnLastSlide: false,
disableOnInteraction: true,
}
})
})
}
}
}
</script>
<style lang='scss'>
$sc:25;
.swiper-container img{
width:100%;
height: 175/$sc+rem;
.swiper-pagination{
text-align: right;
z-index: 1;
}
}
.newspart{
display: flex;
height: 70/$sc+rem;
margin:5/$sc+rem;
img{
width: 110/$sc+rem;
height: 70/$sc+rem;
padding-right:22/$sc+rem;
}
.sor{
margin-top: 15/$sc+rem;
}
}
</style>
components/page/typenews 这是导航栏对应的数据
<template>
<div>
<!--新闻列表-->
<ul>
<li v-for="item in news" class="newspart">
<div>
<h3>{{item.mtitle}}</h3>
<p class="sor">{{item.media}}</p>
</div>
<div>
<img v-bind:src="item.thumb">
</div>
</li>
</ul>
</div>
</template>
<script>
import axios from 'axios'
import Swiper from 'swiper'
import '../../../node_modules/swiper/dist/css/swiper.css'
export default{
data(){
return{
news:[],//这是从接口中请求的所有数据都存放在这里面
type:''
}
},
created(){ //从接口中请求数据
},
watch:{
$route:{
handler(n){
this.type=n.params.type;
this.getData()
},
immediate:true
}
},
methods:{
getData(){
this.$jsonp(`http://cre.mix.sina.com.cn/api/v3/get?cateid=1&cre=tianyi&mod=${this.type}&merge=3&statics=1&length=20&up=2&down=0&fields=media&_=1543849575332`
).then((res)=>{
this.news=res.data.filter((item,index)=>{
return index<40 &&item.mtitle
})
console.log(this.news)
})
}
}
}
</script>
<style lang='scss'>
$sc:25;
.swiper-container img{
width:100%;
height: 175/$sc+rem;
.swiper-pagination{
text-align: right;
z-index: 1;
}
}
.newspart{
display: flex;
height: 70/$sc+rem;
margin:5/$sc+rem;
justify-content: space-between;
img{
width: 110/$sc+rem;
height: 70/$sc+rem;
padding-right:22/$sc+rem;
}
.sor{
margin-top: 20/$sc+rem;
}
}
</style>
![](https://i-blog.csdnimg.cn/blog_migrate/92fe24f0b5dfde36002f4ecd76588b71.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a2dd00440a4341d3c2cf1f7805652a14.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1a4179169ff2524ca8931c92a6733639.png)