豆瓣电影列表 + 详情 VUE 2.X 初使用 H5 手机预览 混合开发(一)

概要

IDE: HBuilder
使用框架: JQuery 3.3.1 Vue2.x
描述: 利用 豆瓣 API https://github.com/Pingsh/-Api 创建豆瓣电影列表和电影简介

豆瓣电影列表

  • 很简单的两个页面, 豆瓣电影列表及电影详情, 不存在什么 UI 审美

实现和效果图

列表的 css 基于 mui.css , 主要代码和效果图如下 :

HBuilder 有 "边看边改模式, 比较方便"

<div id="pull-subject-list" class="mui-content mui-scroll-wrapper">
	<div class="mui-scroll">
		<div class="mui-input-row mui-search">
			<input v-model="search" debounce="500" id="search" type="search" class="mui-input-speech mui-input-clear" placeholder="搜索" value=""></div>
			<!--数据列表-->
			<ul class="mui-table-view mui-table-view-chevron" v-for="subject in subjects" track-by="id" @tap="show_detail(subject)">
				<li class="mui-table-view-cell mui-media">
					<a style="padding:10px 35px 10px 10px;">
						<img class="img_show mui-pull-left" :src="subject.images.small" />
						<div class="mui-media-body" style="padding-left:10px;margin-top: 3px;">
								{{subject.title}}
						</div>
						<h5 style="float:right;" class="mui-ellipsis">{{subject.mainland_pubdate}}</h5>
					</a>
				</li>
		      </ul>
	</div>
</div>

var base_url = "https://api.douban.com/v2/movie/"
var pi = startIndex;
var startIndex = 0;
var movieCount = 10;

mui.init({
	pullRefresh: {
		container: '#pull-subject-list',
		down: {
			style: 'circle',
			callback: pulldownRefresh
		},
		up: {
			auto: true,
			contentrefresh: '正在加载...',
			callback: pullupRefresh
		}
	}
});

jQuery.ajax({
	url: base_url + '/in_theaters',
	data: {
		apikey: '0b2bdeda43b5688921839c8ecb20399b',
		city: '%E5%8C%97%E4%BA%AC',
		start: startIndex,
		count: movieCount,
		client: 'somemessage',
		udid: 'ddddddd'
	},
	dataType: 'jsonp',
	success: function(data) {
		if(data && data.subjects.length > 0) {
			mui('#pull-subject-list').pullRefresh().endPullupToRefresh(data.subjects.length < movieCount); //参数为true代表没有更多数据了。
			if(pi == 0) {
				vm.subjects = data.subjects;
			} else {
				vm.subjects = vm.subjects.concat(data.subjects);
			}
			mui('#pull-subject-list').pullRefresh().endPulldownToRefresh(true);

			startIndex += movieCount;
		}
	}
});

var vm = new Vue({
	el: '#pull-subject-list',
	data: {
		search: '',
		subjects: []
	},
	methods: {
		show_detail: function(subject) {
		console.log("id: " + subject.id);
		localStorage.setItem("id", subject.id);
		mui.openWindow({
			url: "movie_detail.html",
			show: {
				autoShow: true, //页面loaded事件发生后自动显示,默认为true  
				aniShow: "slide-in-right", //页面显示动画,默认为”slide-in-right“;  
				duration: 500 //页面动画持续时间,Android平台默认100毫秒,iOS平台默认200毫秒;  
			}
		});
	},
	getData: function() {
		setTimeout(getSubjects(), 1500);
	},
	created: function createData() {
			this.getData();
	}
});

vm.$watch('search', function() {
	startIndex = 0;
	mui('#pull-subject-list').pullRefresh().refresh(true);
	getSubjects();
	}, {
		deep: true
	});

敲黑板的知识点

v-model 是 Vue 中的语法糖, 用作双向绑定, 达到的效果是: 输入变化即搜索. 豆瓣没有公开搜索的 API ,此处只做了样式.

v-for 是 Vue 中的语法糖, 常见于列表. 新建 vue 对象之后, 在 data:中对页面的数据进行编辑, 实体的属性名称可以不写, 联网之后直接使用. 在 css 中使用时, 有两种方式: 一种是采用上面的 {{subject.title}} , 写在标签中; 另一种是使用 v-bind 或 v-model . 实际项目中, 更建议第二种方式, 加载缓慢时, 不会出现 {{}} 占位的情况. 建议实际敲一遍, 看看效果.

track-by 配合 v-for 使用, 用来复用dom和原来的作用域. 这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出. Vue 2.x 的推荐是这样 :

<div v-for="item in items" :key="item.id">
  <!-- 内容 -->
</div>

官方说法: 建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

jsonp 本来是准备用原生的方式写联网请求, 一直请求不到数据, 以前用 Android 没这毛病呀… 查找了很久, 发现是跨域问题, 也算是豆瓣的保护机制… 故, 引入 JQuery. dataType: 设置为 jsonp: , 即可成功访问.

电影详情

  • 详情的预期需求是, 如果文字超过 4 行, 不显示右下角的 icon; 如果超过 4 行, 显示 icon , 且默认收起; 点击 icon, 改变 icon 方向, 展示所有文本.

实现和效果图

影片简介超过四行-初始状态

影片简介超过四行-展开状态

影片简介不足四行

<header class="mui-bar mui-bar-nav " style="background: #45B1F7;height: 50px;">
	<a class="mui-action-back mui-icon mui-icon-back mui-pull-left"></a>
	<h5 class="mui-title" style="color: white;font-size: 1.1em; margin-top: 3px;">电影详情</h5>
</header>

<div id="movie-detail" class="mui-content mui-fullscreen" style="background: #ECF7FE;background-size: 100%,100%;">
	<div style="width: 60%; margin: 20px;">

	<div class="movie-title" id="title">{{subject.title}}</div>

	<span id="year" class="movie-detail-text">{{ subject.year }}&nbsp;</span>
	<span id="genres" class="movie-detail-text" v-for="gen in subject.genres">/{{gen}}</span>
	<div id="original-title" class="movie-detail-text">原名: &nbsp;<span>{{subject.original_title}}</span></div>
	<div id="mainland-pubdate" class="movie-detail-text">上映时间: &nbsp;<span>{{subject.mainland_pubdate}}</span></div>
	<div id="durations" class="movie-detail-text" v-for="duration in subject.durations">片长: &nbsp;{{duration}}</div>
</div>

<div class="movie-mark">
	<div class="movie-detail-text">豆瓣评分</div>
	<div style="font-size: 30px; line-height: 100%;" id="average">{{subject.rating.average}}</div>
	<div class="movie-detail-text" id="ratings-count">{{subject.ratings_count}}人</div>
</div>

<div class="movie-dash"></div>

<div style="padding: 30px 20px; background: #ECF7FE;">
	<div class="movie-detail-text" style="font-size: 18px; margin-bottom: 20px;">简介</div>
		<div ref="singleLine" style="line-height: 1.3em;">&nbsp;</div>
		<div id="summary-part1" :class="{foldSummary:fold, unfoldSummry:!fold}" ref="movieSummary">{{subject.summary}}</div>
		<a id="summary-part2" class="mui-icon mui-pull-right mui-icon-arrowup" v-on:click="handleFold" ref="foldIcon" v-show="showIcon"></a>
	</div>
</div>
var sub = new Vue({
	el: '#movie-detail',
	data: {
		subject: {
				genres: [],
				rating: [average],
				durations: []
		},
		fold: false,
		showIcon: true,
	},
	methods: {
		handleFold: function() {
			this.fold = !this.fold;
		},
		getData: function() {
			setTimeout(getMovieDetail(), 100);
		}
	},
	created: function create() {
		this.getData();
	},
	watch: {
		fold: function(val) {
			var icon = this.$refs.foldIcon;
			if(this.fold) {
				icon.setAttribute('class', 'mui-icon mui-pull-right mui-icon-arrowup');
			} else {
				icon.setAttribute('class', 'mui-icon mui-pull-right mui-icon-arrowdown');
			}
		}
		// 图标是否显示不能写在watch, 事件没有被主动触发
}
				/*,
				//不能写在 mounted, 数据暂未获取
								mounted: function() {
									this.$nextTick(function() {
										var content = this.$refs.movieSummary;
										var test = this.$refs.test;
										console.log(content.innerHTML);
										
										for(var i = 0, len = content.style.length; i < len; i++) {
											var prop = content.style[i]
											console.log(prop); //遍历样式width;height;background-color;
											console.log(content.style.getPropertyValue(prop)); //取得样式里面的值;   
										}
										
										if(content.style.display == 'block') {
											this.showIcon = false;
										} else {
											this.showIcon = true;
										}
									})
								}*/
			});

function getMovieDetail() {
	jQuery.ajax({
		url: movieurl,
		data: {
			apikey: '0b2bdeda43b5688921839c8ecb20399b',
			city: '%E5%8C%97%E4%BA%AC',
			client: 'somemessage',
			udid: 'ddddddd'
		},
		dataType: 'jsonp',
		success: function(data) {
			if(data) {
				sub.subject = data;
				//sub.subject.summary = "测试短评";
			}
		},
		complete: function() {
			sub.$nextTick(function() {
				var singleHeight = parseInt(this.$refs.singleLine.offsetHeight);
				var height = parseInt(this.$refs.movieSummary.offsetHeight);

				//此时只能获取行内样式, 不能获取 css 中 class 的样式
				//console.log(jQuery("#summary-part1").height());
				if(Math.round(height / singleHeight) > 4) {
					this.showIcon = true;
					this.fold = true;
				} else {
					this.showIcon = false;
					this.fold = false;
				}
			})
		}
	});
}

敲黑板的知识点 +2

Vue的生命周期 写出列表页面之后, 开始思考, 既然 Android 中有生命周期, 很多操作都和生命周期息息相关, JS 中应该也是同理(PS: 来自移动开发人员的直觉). 在此不一一赘述, 感兴趣可以查看这篇文章: Vue 生命周期. 在没有理解生命周期之前, 曾经尝试在mounted 中利用 $nextTick 对样式进行修改, 理所当然失败啦.

ref Vue 中直接操作 DOM 元素,用它进行注册, 更常用的方式和组件相关. 此处只用它获取元素, 如果愿意, 这份代码中用 id 或者 name 等其他方式替代也没有问题.

:class 缩写, 相当于

<div v-bind:class="{ foldSummary:fold }"></div>

类似的还有

<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>

v-show 顾名思义, 布局是否显示, 类似的还有 v-if. 两者的区别是:

在v-show中,元素是一直存在的, 当v-show为false, 元素display:none只是隐藏了而已.
在v-if, 元素不是一直存在, 判断是否加载固定的内容, 如果为真, 则加载; 为假时, 则不加载. 控制元素插进来或者删除, 而不是隐藏.

v-show 在加载时, 比 v-if 消耗高; v-if 的切换消耗比 v- show 高.
结合这些分析, icon 是否显示, 只在初始化数据时进行了判断, v-if 更加合理. 但是, 我写的是 v-show , 这是个错误示范. 

前端的其他框架中也有类似处理, 比如 AngularJS 中的 ng-ifng-show.

内联样式和css中的样式 数据请求成功后, 需要设置 icon 是否显示, 如果将关键样式写在 css 中, 而非标签内的 style 内, 修改无效. 这里用了个小技巧, 在简介上方加上一行空白行, 获取简介的文本高度, 超过 4 行则显示 icon; 未超过则不显示.

总结

这个 demo 是 2018年初写的, 当时刚接触 H5 和 Vue, 写法一点也不 JavaScript, 有很多缺陷(轻点拍砖 哈哈哈哈), 年终翻出来看了看, 希望能给初次接触 H5 的伙伴们一些帮助.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 2.x 版本中,你可以使用 pandas 库进行数据处理和分析,但需要在后端服务器进行处理,并将处理后的数据传递给 Vue 前端进行展示。 以下是一般的步骤: 1. 在后端服务器中使用 Python 安装 pandas 库。可以使用 pip 命令运行 `pip install pandas` 进行安装。 2. 在后端服务器编写一个接口或路由,用于处理数据并返回给前端。你可以使用 Flask、Django 或其他后端框架来创建这个接口。 3. 在后端服务器的接口或路由中,导入 pandas 库并使用它进行数据处理。例如,你可以读取 CSV 文件、执行数据筛选、聚合或其他操作。 4. 将处理后的数据转为 JSON 格式,并返回给前端。可以使用 Flask 的 `jsonify` 方法将数据转为 JSON 格式,并通过接口返回给前端。 5. 在 Vue 前端中,使用 axios 或其他类似的库发送 AJAX 请求调用后端接口,并获取返回的数据。在 Vue 组件中可以使用生命周期钩子函数 `mounted` 或 `created` 来发送请求,并将返回的数据保存到 Vue 的 data 中。 6. 在 Vue 组件中,利用数据绑定和模板语法将数据展示在页面上。你可以使用 v-for 指令来遍历数据,并将其渲染为 HTML 元素。 需要注意的是,在 Vue 的前端中不能直接使用 pandas 库进行数据处理,因为 Vue 是运行在浏览器中的 JavaScript 框架,而 pandas 是一个在后端运行的 Python 库。因此,你需要通过后端服务器来进行数据处理,并将处理后的结果传递给前端。 希望这些步骤能帮助你在 Vue 2.x 版本中使用 pandas 进行数据处理和展示

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值