2019-09-12 12:16:25 qq_33555718 阅读数 128
先说点题外话,本来是写在简书上面的文章,现在简书不支持发布了,只能在csdn上上传了....
WebView对于前端开发的小伙伴来讲肯定不陌生,功能是很轻大的,就是一个而普通的html界面。今天主要讲一下小程序使用webview的场景。
一、先说下需求背景,我们最近需要在微信小程序开发一个富文本的功能出来,如果是在传统的浏览器开发是很简单的,因为html提供了强大的渲染能力。我对小程序渲染富文本的方案也做了尝试,分别使用了rich-text、wxparse、mpvue-parse、html2wxml,后三个都是第三方的渲染库。
1.rich-text是微信提供的解析方案,渲染流畅但是效果很差劲,别说数学公式就是某些常用的html布局都渲染不出来,更糟糕的是渲染节点是text格式,导致我们不可以使用csstree对dom进行二次渲染和样式优化。
2.mpvue-parse是基于wxparse做的mpvue的扩展,官方说是很强大,扩展了图片预览之类的功能,并且支持图片尺寸设置,实际用下来还可以,渲染之后的效果也是dom结构,样式控制也比较简单。缺点:可能是需要本地动态解析**html导致复杂的dom结构会出现小程序界面卡死**,所以放弃了
3.html2wxml是一种服务器解析富文本的方案,这个是可以解决界面卡死的问题,他本质就是把html解析为wxml,这个框架针对**数学题目有些是渲染不完整的**,不过它是支持自己搭建渲染库的,不过还需要后台人员配合维护所以也放弃了。这个是项目介绍html2wxml 微信小程序富文本渲染组件 HTML / Markdown 富文本解析-小程序-QwqOffice软件工作室。可以加下作者联系方式,因为一些使用场景没有详细说到,比如最新的解析地址,还有老的地址解析text格式文本会导致小程序view不更新的情况。
4.wxparse是对公式的渲染效果是这几个里面最好的 ,不会丢失内容,不过使用过程中发现解析效果并不会完全转换为dom结构,有些是直接转化为微信的rich-text,所以样式的控制就比较麻烦了。下面就是解析的一些rich-text的结构:
![在这里插入图片描述](https://img-blog.csdnimg.cn/201909121213266.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNTU1NzE4,size_16,color_FFFFFF,t_70)

最终选择了WebView,这个效果就不用说了,唯一的缺点就是体验不好了,毕竟会脱离小程序的原生界面去载入一个html链接,不管是加载速度还是体验会有些割裂感,不过一些比较大的厂商的小程序也是这样处理的,比如拼多多的活动页面、腾讯文档的内容页面(也必须用webview去渲染)。下面是一些渲染结果:
在这里插入图片描述

二、下面讲一下微信小程序使用WebView的注意事项(只是目前发现的一些)
1.使用前提:管理平台需要配置webview域名,不然真机无法进入页面;webview请求数据接口地址如果没有加入域名访问在小程序里面是看不到错误提示的,这点要注意。
2.小程序打开调试并不能不获WebView 的打印的错误信息,导致出现问题不好调试,只能推消息通知给小程序:
在这里插入图片描述
3.没有配置的webview域名在ios真机上面打开调试会出现偶发性的白屏,这个推断应该是网络导致的,但是关闭掉调试之后就会好了。
4.代码兼容性问题,由于微信webview使用的内核特殊导致代码存在兼容性问题,比如:
*{
margin:0; padding:0;
-webkit-touch-callout:none;
/系统默认菜单被禁用/
-webkit-user-select:none; /webkit浏览器/
-khtml-user-select:none; /早期浏览器/
-moz-user-select:none;/火狐/ -ms-user-select:none; /IE10/
user-select:none;
}
以上是禁用浏览器复制文本的css属性,这个在小程序webview上面是没效果的,只能通过js去设置了:document.documentElement.style.webkitTouchCallout = “none”; //禁止弹出菜单
document.documentElement.style.webkitUserSelect = “none”;//禁止选中

5.某些标签点击在ios会出现点击状态我尝试了好多方案还是没有禁用掉,大家如果有好的方式可以留言…
6.webview无法自定义小程序的导航栏7.overflow的属性会导致ios上面活动滚动条不流畅,可以设置-webkit-overflow-scrolling:touch;去解决。
以上就是我使用小程序webview遇到的一些问题。。。

2019-11-04 20:44:54 daimakk123456 阅读数 27

大部分Web应用的富文本内容都是以HTML字符串的形式存储的,通过HTML文档去展示HTML内容自然没有问题。但是,在微信小程序(下文简称为「小程序」)中,应当如何渲染这部分内容呢?

解决方案

wxParse

小程序刚上线那会儿,是无法直接渲染HTML内容的,于是就诞生了一个叫做「 wxParse 」的库。它的原理就是把HTML代码解析成树结构的数据,再通过小程序的模板把该数据渲染出来。

rich-text

后来,小程序增加了「rich-text」组件用于展示富文本内容。然而,这个组件存在一个极大的限制: 组件内屏蔽了所有节点的事件 。也就是说,在该组件内,连「预览图片」这样一个简单的功能都无法实现。

web-view

再后来,小程序允许通过「web-view」组件嵌套网页,通过网页展示HTML内容是兼容性最好的解决方案了。然而,因为要多加载一个页面,性能是较差的。

当「WePY」遇上「wxParse」

基于用户体验和功能交互上的考虑,我们抛弃了「rich-text」和「web-view」这两个原生组件,选择了「wxParse」。然而,用着用着却发现,「wxParse」也不能很好地满足需要:

  • 我们的小程序是基于「WePY」框架开发的,而「wxParse」是基于原生的小程序编写的。要想让两者兼容,必须修改「wxParse」的源代码。
  • 「wxParse」只是简单地通过image组件对原img元素的图片进行显示和预览。而在实际使用中,可能会用到云存储的接口对图片进行缩小,达到「 用小图显示,用原图预览 」的目的。
  • 「wxParse」直接使用小程序的video组件展示视频,但是video组件的 层级问题 经常导致UI异常(例如把某个固定定位的元素给挡了)。

此外,围观一下「wxParse」的代码仓库可以发现,它已经两年没有迭代了。所以就萌生了基于「WePY」的组件模式重新写一个富文本组件的想法,其成果就是「WePY HTML」项目。

#实现过程

###解析HTML
首先仍然是要把HTML字符串解析为树结构的数据,我采用的是「特殊字符分隔法」。HTML中的特殊字符是「<」和「>」,前者为开始符,后者为结束符。

•如果待解析内容以开始符开头,则截取 开始符到结束符之间 的内容作为节点进行解析。
•如果待解析内容不以开始符开头,则截取 开头到开始符之前 (如果开始符不存在,则为末尾)的内容作为纯文本解析。
•剩余内容进入下一轮解析,直到无剩余内容为止。

对web前端这门技术感兴趣的小伙伴可以加入到我们的学习圈来,编程工作第六个年头了,与大家分享一些学习方法,实战开发需要注意的细节。784-783-012 秋裙。从零基础开始怎么样学好前端。看看前辈们是如何在编程的世界里傲然前行!不停更新最新的教程和学习方法(web前端系统学习路线,详细的前端项目实战教学视频,PDF),有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入。我们会一起结伴同行学习前端我们是认真的

正如下图所示:

image.png

为了形成树结构,解析过程中要维护一个上下文节点(默认为根节点):

•如果截取出来的内容是开始标签,则根据匹配出的标签名和属性,在当前上下文节点下创建一个子节点。如果该标签不是自结束标签(br、img等),就把上下文节点设为新节点。
•如果截取出来的内容是结束标签,则根据标签名关闭当前上下文节点(把上下文节点设为其父节点)。
•如果是纯文本,则在当前上下文节点下创建一个文本节点,上下文节点不变。
过程正如下面的表格所示:

image.png

经过上述流程,HTML字符串就被解析为节点树了。

对比
把上述算法与其他类似的解析算法进行对比(性能以「解析10000长度的HTML代码」进行测定):

image.png

可见,在不考虑容错性(产生错误的结果,而非抛出异常)的情况下,本组件的算法与其余两者相比有压倒性的优势,符合小程序「 小而快 」的需要。而一般情况下,富文本编辑器所生成的代码也不会出现语法错误。因此,即使容错性较差,问题也不大(但这是需要改进的)。

#模板渲染

树结构的渲染,必然会涉及到子节点的 递归 处理。然而,小程序的模板并不支持递归,这下仿佛掉入了一个大坑。

看了一下「wxParse」模板的实现,它采用简单粗暴的方式解决这个问题:通过13个长得几乎一模一样的模板进行嵌套调用(1调用2,2调用3,……,12调用13),也就是说最多可以支持12次嵌套。一般来说,这个深度也足够了。

由于「WePY」框架本身是有构建机制的,所以不必手写十来个几乎一模一样的模板,通过一个构建的插件去生成即可。

以下为需要重复嵌套的模板(精简过),在其代码的开始前和结束后分别插入特殊注释进行标识,并在需要嵌入下一层模板的地方以另一段特殊注释(「」)标识:

<!-- wepyhtml-repeat start -->
<template name="wepyhtml-0">
	<block wx:if="{{ content }}" wx:for="{{ content }}">
		<block wx:if="{{ item.type === 'node' }}">
			<view class="wepyhtml-tag-{{ item.name }}">
				<!-- next template -->
			</view>
		</block>
		<block wx:else>{{ item.text }}</block>
	</block>
</template>
<!-- wepyhtml-repeat end -->

以下是对应的构建代码(需要安装「 wepy-plugin-replace 」):

web前端开发学习Q-q-u-n:784783012 ,分享学习的方法和需要注意的小细节,不停更新最新的教程和学习方法(详细的前端项目实战教学视频,PDF)
// wepy.config.js
{
	plugins: {
		replace: {
			filter: /\.wxml$/,
			config: {
				find: /<\!-- wepyhtml-repeat start -->([\W\w]+?)<\!-- wepyhtml-repeat end -->/,
				replace(match, tpl) {
					let result = '';
					// 反正不要钱,直接写个20层嵌套
					for (let i = 0; i <= 20; i++) {
						result += '\n' + tpl
							.replace('wepyhtml-0', 'wepyhtml-' + i)
							.replace(/<\!-- next template -->/g, () => {
								return i === 20 ?
									'' :
									`<template is="wepyhtml-${ i + 1 }" wx:if="{{ item.children }}" data="{{ content: item.children"></template>`;
							});
					}
					return result;
				}
			}
		}
	}
}

然而,运行起来后发现,第二层及更深层级的节点都没有渲染出来,说明嵌套失败了。再看一下dist目录下生成的wxml文件可以发现,变量名与组件源代码的并不相同:

<block wx:if="{{ $htmlContent$wepyHtml$content }}" wx:for="{{ $htmlContent$wepyHtml$content }}">

「WePY」在生成组件代码时,为了避免组件数据与页面数据的变量名冲突,会 根据一定的规则给组件的变量名增加前缀 (如上面代码中的「htmlContenthtmlContentwepyHtml$」)。所以在生成嵌套模板时,也必须使用带前缀的变量名。

先在组件代码中增加一个变量「thisIsMe」用于识别前缀:

<!-- wepyhtml-repeat start -->
<template name="wepyhtml-0">
	{{ thisIsMe }}
	<block wx:if="{{ content }}" wx:for="{{ content }}">
		<block wx:if="{{ item.type === 'node' }}">
			<view class="wepyhtml-tag-{{ item.name }}">
				<!-- next template -->
			</view>
		</block>
		<block wx:else>{{ item.text }}</block>
	</block>
</template>
<!-- wepyhtml-repeat end -->

然后修改构建代码:

replace(match, tpl) {
	let result = '';
	let prefix = '';

    // 匹配 thisIsMe 的前缀
	tpl = tpl.replace(/\{\{\s*(\$.*?\$)thisIsMe\s*\}\}/, (match, p) => {
		prefix = p;
		return '';
	});

	for (let i = 0; i <= 20; i++) {
		result += '\n' + tpl
			.replace('wepyhtml-0', 'wepyhtml-' + i)
			.replace(/<\!-- next template -->/g, () => {
				return i === 20 ?
					'' :
					`<template is="wepyhtml-${ i + 1 }" wx:if="{{ item.children }}" data="{{ ${ prefix }content: item.children }}"></template>`;
			});
	}

	return result;
}

至此,渲染问题就解决了。

#图片
为了节省流量和提高加载速度,展示富文本内容时,一般都会按照所需尺寸对里面的图片进行缩小,点击小图进行预览时才展示原图。这主要涉及节点属性的修改:

•把图片原路径(src属性值)存到自定义属性(例如「data-src」)中,并将其添加到预览图数组。
•把图片的src属性值修改为缩小后的图片URL(一般云服务商都有提供此类URL规则)。
•点击图片时,使用自定义属性的值进行预览。
为了实现这个需求,本组件在解析节点时提供了一个钩子( onNodeCreate ):

onNodeCreate(name, attrs) {
	if (name === 'img') {
		attrs['data-src'] = attrs.src;
		// 预览图数组
		this.previewImgs.push(attrs.src);
		// 缩图
		attrs.src = resizeImg(attrs.src, 640);
	}
}

对应的模板和事件处理逻辑如下:

<template name="wepyhtml-img">
	<image class="wepyhtml-tag-img" mode="widthFix" src="{{ elem.attrs.src }}" data-src="{{ elem.attrs['data-src'] || elem.attrs.src }}" @tap="imgTap"></image>
</template>
// 点击小图看大图
imgTap(e) {
	wepy.previewImage({
		current: e.currentTarget.dataset.src,
		urls: this.previewImgs
	});
}

#视频

在小程序中,video组件的层级是较高的(且无法降低)。如果页面设计上存在着可能挡住视频的元素,处理起来就需要一些技巧了:

•隐藏video组件,用image组件(视频封面)占位;
•点击图片时,让视频全屏播放;
•如果退出了全屏,则暂停播放。
相关代码如下:

<template name="wepyhtml-video">
	<view class="wepyhtml-tag-video" @tap="videoTap" data-nodeid="{{ elem.nodeId }}">
		<!-- 视频封面 -->
		<image class="wepyhtml-tag-img wepyhtml-tag-video__poster" mode="widthFix" src="{{ elem.attrs.poster }}"></image>
		<!-- 播放图标 -->
		<image class="wepyhtml-tag-img wepyhtml-tag-video__play" src="./imgs/icon-play.png"></image>
		<!-- 视频组件 -->
		<video style="display: none;" src="{{ elem.attrs.src }}" id="wepyhtml-video-{{ elem.nodeId }}" @fullscreenchange="videoFullscreenChange" @play="videoPlay"></video>
	</view>
</template>

{web前端开发学习Q-q-u-n:784783012 ,分享学习的方法和需要注意的小细节,不停更新最新的教程和学习方法(详细的前端项目实战教学视频,PDF)
	// 点击封面图,播放视频
	videoTap(e) {
		const nodeId = e.currentTarget.dataset.nodeid;
		const context = wepy.createVideoContext('wepyhtml-video-' + nodeId);
		context.play();
		// 在安卓微信下,如果视频不可见,则调用play()也无法播放
		// 需要再调用全屏方法
		if (wepy.getSystemInfoSync().platform === 'android') {
			context.requestFullScreen();
		}
	},
	// 视频层级较高,为防止遮挡其他特殊定位元素,造成界面异常,
	// 强制全屏播放
	videoPlay(e) {
		wepy.createVideoContext(e.currentTarget.id).requestFullScreen();
	},
	// 退出全屏则暂停
	videoFullscreenChange(e) {
		if (!e.detail.fullScreen) {
			wepy.createVideoContext(e.currentTarget.id).pause();
		}
	}
}

本文分享就到这里了。

2016-10-11 19:48:23 zhangsx101 阅读数 8230

简单介绍

小程序是一种不需要下载安装即可使用的应用。

实质

微信小程序就是Hybrid技术的应用。
Hybrid App(混合模式移动应用)。
小程序能够更多的可以更多的调用手机本身的功能(如位置信息,摄像头等)。

如何开发

  • 主要技术:WXML(HTML5)、WXSS(CSS)、JavaScript
  • 开发思路:使用app开发的数据绑定渲染的思路,掌握微信提供的控件和接口,通过javascript实现业务处理和服务器交互等操作。

官方文档地址:微信小程序官方文档

开发工具下载安装和使用

1.根据系统下载对应的安装软件
2.下载nodejs 安装
3.安装微信开发者工具
4.登录(微信开发者账号)
5.选择无appid(没装nodejs是没有这个选项)

框架

逻辑层(App Service)

小程序开发框架的逻辑层是由JavaScript编写。
逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。小程序再次基础上做了一些修改方便开发:

  • 增加 App 和 Page 方法,进行程序和页面的注册。

注册程序:

App() 函数用来注册一个小程序。接受一个 object 参数,其指定小程序的生命周期函数等。
如:app.js 。(注:App只能在app.js中注册,且不能注册多个)
注:不要在定义于 App() 内的函数中调用 getApp() ,使用 this 就可以拿到 app 实例。在其他js文件中我们通过:
var appInstance = getApp()获取小程序实例。

App({
  //当程序初始化的时候
  onLaunch: function () {
  },
  // 小程序显示的时候触发
  onShow:function(){
    console.log("生命周期函数-监听小程序显示的时候触发");
  },
  // 小程序隐藏的时候触发
  onHide(){
    console.log("生命周期函数-监听小程序隐藏的时候触发");
  },
  // 全局属性
  globalData:{
    pass:"12345678"
  }
})

注册页面:

Page() 函数用来注册一个页面。接受一个 object 参数,其指定页面的初始数据、生命周期函数、事件处理函数等。
如:test.js

// 获取应用实例
var app = getApp();
Page({
  //初始化数据
  data:{
    pass:null
  },
  // 事件处理函数
  toNavi:function(){
    //跳转到navi.wxml页面
    wx.navigateTo({
      url:"../navi/navi",
      success:function(){
        console.log("成功跳转navi");
      }
    });
  },
  onLoad:function(options){
    // 页面初始化 options为页面跳转所带来的参数

    //setData 函数用于将数据从逻辑层发送到视图层,同时改变对应的 this.data 的值。
    this.setData({
      pass:app.globalData.pass
    });
  },
  onReady:function(){
    // 页面渲染完成
  },
  onShow:function(){
    // 页面显示
  },
  onHide:function(){
    // 页面隐藏
  },
  onUnload:function(){
    // 页面关闭
  }
})

附:test.wxml中的代码很简单:
<view>密码是:{{pass}}</view>
  • 每个页面有独立的作用域,并提供模块化能力。

我们可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 才能对外暴露接口。

// common.js
function sayHello(name) {
  console.log('Hello ' + name + '!')
}
module.exports = {
  sayHello: sayHello
}

//在需要使用这些模块的文件中,使用 require(path) 将公共代码引入。
var common = require("../../common/common.js");//改成自己的路径
Page({
  helloMINA: function() {
    common.sayHello('MINA')
  }
})

视图层

WXML:
具有什么能力:

  • 数据绑定(语法:双大括号将变量包起来)
    内容属性:
//test.wxml
<view>{{message}}<view>
//test.js
Page({
  data:{
    message:"Hello"
  }
});

最后页面显示结果为:Hello

组件属性:

//test.wxml
<view id="item-{{id}}">123456<view>
//test.js
Page({
  data:{
    message:"Hello"
    id:1
  }
});

看如下效果:
这里写图片描述

控制属性:(需要在双引号之内)

//test.wxml
<!--条件渲染 bol为true显示,false隐藏-->
<view wx:if="{{bol}}">条件渲染显示<view>
//运算符
//<view>{{bol?"正":"反"}}</view>
<block wx:if="{{true}}">
<view>第一个view</view>
<view>第二个view</view>
</block>
<text hidden="{{false}}">我是一段文本</text>
<view wx:for="{{arr}}">项目:{{item}}</view>
<!--组合-->
<view wx:for="{{[3,2,1]}}">{{item}}</view>
//test.js
Page({
  data:{
    message:"Hello",
    id:1,
    bol:false,
    arr:[1,2,3,4,5]
  }
});
  • 条件渲染(见上)
    wx:if
    block wx:if

  • 列表渲染(见上)
    wx:for
    block wx:for

  • 模板(拥有独立作用域)

//test.wxml
<!--定义一个模板-->
<template name="object">
<view>第一个对象:{{a}}</view>
<view>{{b}}</view>
</template>
<!--使用模板-->
<template is="object" data="{{a:1,b:2}}"></template>

or

<template is="object" data="{{...obj1}}"></template>

WXSS:

2016-11-08 20:24:16 weixin_jack 阅读数 2195

「H5程序俱乐部」是一个专注微信小程序学习交流,相关外包/招聘需求信息发布的微信公众号
图片描述

源代码下载地址:
http://pan.baidu.com/s/1nv8m1ip

基于微信小程序的一个查找检索菜谱的应用

功能

分类检索菜谱
发现最新菜谱
根据菜谱名搜索菜谱
用到的API

页面路由
列表渲染
带参数页面跳转
navigator
scrollview下拉加载更多

效果
图片描述

开发工具
微信Web开发者工具 0.10.101100

源代码下载地址:
http://pan.baidu.com/s/1nv8m1ip

「H5程序俱乐部」微信号:wxappclub 或者 微信扫一扫关注
图片描述

2017-01-15 22:42:49 androidstarjack 阅读数 1360

什么是微信小程序?

官方定义

小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。也体现了“用完即走”的理念,用户不用关心安装太多应用的问题。应用将无处不在,所示可用,但又无需安装卸载。

特点:

  • 不是网页(HTML5)
  • 即用即走,随手可得
  • 拥有离线能力
  • 一次开发,多端兼容
  • 优美的操作体验(用native的控件来渲染的)
  • 存在于云端

例如:今日头条,美团,尤其是旅游之类的特别多。

native —》javascript

wsml wsss
是以web的开发方式,体验:natived的开发体验 。

开发环境

如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809
微信公众号:终端研发部
(欢迎关注学习和交流)
这里写图片描述

没有更多推荐了,返回首页