app接入网易严选:webview注入js的几个坑

消费贷款app“一刻千金”接入网易严选总结

主要任务列表

  1. 隐藏相关元素
  2. 商品列表页跳转事件绑定
  3. 获取商品信息(skuid比较复杂)

隐藏元素

这部分没什么好讲的,使用原生js的document的api定位元素或者jQuery的选择器定位元素,然后隐藏(hide)或者移除(remove)

阻止列表页的事件

搜索到结果后,点击其中某个商品,希望跳转至改造过的详情页(改变了购买方式)。

搜索列表页的html主要结构如下:

<ul class="list">
    <li class="item">
        <a class="good" data-reactid="aaaaaa">商品1</a>
    </li>
    <li class="item">
        <a class="good" data-reactid="bbbbbb">商品1</a>
    </li>
    <li class="item">
        <a class="good" data-reactid="cccccc">商品1</a>
    </li>
</ul>

以往接入京东、苏宁时,列表页商品跳转都是通过<a>标签设置href的,重新绑定事件,并使用preventDefault,可以防止href的跳转;

严选使用了react技术栈,这里有两个问题:

  1. 没有使用href,跳转是通过绑定事件,而这个事件处理方法是匿名函数,不知道怎么去移除(使用了jquery的off和unbind,都不起作用知识有限,暂留问号???);
  2. 列表页下拉时,加载,所以给每个<a>标签绑定事件,貌似不太友好也不太靠谱。

最后,采用事件委托的方式,只需给<ul>绑定一个点击事件,通过判断所点击当前元素,找出<a>标签所带的商品信息(取出属性data-reactid的值)。使用stopPropagation方法,可以阻断<a>的点击事件执行,完美。同时,也解决了下拉加载的问题。

使用jQuery:

$(‘ul‘).off(‘click‘).on(‘click‘, ‘.item‘, function(e) {
    e.stopPropagation();
    //e.currentTarget 当前点击的‘.item‘元素
    var tag_a = $(e.currentTarget).find(‘a.good‘);
    var data_reactid = tag_a.attr(‘data-reactid‘);
    var product_id = data_reactid.match(/\$\d+/g)[0].replace(‘$‘, ‘‘);
    var obj = {
        link: ‘http://m.you.163.com/item/detail?id=‘ + product_id,
        type: ‘001‘
    };

    console.log(obj);
    postData(obj);  //postData是与app通信的方法
});

原生js:

var ul = document.getElementsByClassName(‘list‘);
if(ul.length > 0) {
    ul.addEventListener(‘click‘, function(e){
        e.stopPropagation();
        var path = e.path();//文档流
        var a = path.filter(item => item.tagName == ‘A‘)//寻找到a标签
        var data_reactid = a[0].getAttribute(‘data-reactid‘);
        var obj = {
            link: ‘http://m.you.163.com/item/detail?id=‘ + product_id,
            type: ‘001‘
        };

        console.log(obj);
        postData(obj);//postData是与app通信的方法
    })
}

使用事件委托的方式,还有个很大的好处。如果循环给<a>标签绑定点击事件,导致该页面存在大量事件处理程序,会影响性能。

在测试时,一直有个奇怪的问题:大量情况下,能确定该段js完整注入并执行,但是通过调试,就是观察不到ul的click事件;只有很小的几率成功。

并且webview注入该js时,确定是在页面渲染完成后才注入的。

后来猜想问题可能是react-router生命周期导致的,<ul>这一部分其实是在子路由里面,通过锚点形式。所以webview认为的页面渲染完成,可能其实不包括这段hash路由。

最后尝试将该事件绑定在<body>上,完美解决。

获取商品信息--skuid

京东、苏宁的商品id,在url上可以很直观地的出来;

而网易严选的商品页面,url中的search部分也有类似id的字段。只可惜,此id并不是需要下单商品的skuid。因为同样商品,不同规格(颜色、尺码等)时,skuid是不一样的。

经过大量不同商品页面的分析(其实也就试了两个)。

在商品详情页和选择规格的页面,有一个jsonData的全局变量,其中jsonData.skuMap类似下面的形式:

该商品有两个规格(颜色和尺码需要选择),很容易分析出,该如何确定,寻找skuid了。

  1. 获得所选规格(颜色、尺码)的值keyList;
  2. 将jsonData.skuMap转为[k,v]的列表skuMapList(使用Object.entries);
  3. 根据keyLlist,过滤筛选skuMapList,正常情况下,skuMapList只剩下一条数据。
function getSkuId() {
    var spec_cons = document.getElementsByClassName(‘u-format‘);
    var selObject = []
    for (var i = 0; i < spec_cons.length - 1; i++) {
        var element = spec_cons[i];
        var selected = element.getElementsByClassName(‘tab-sel‘)[0];
        if (selected) {
            var str = selected.getAttribute(‘data-reactid‘);
            var kv = str.match(/\$\d+/g);
            var item = {
                id: kv[0].replace(‘$‘, ‘‘),
                value: kv[1].replace(‘$‘, ‘‘)
            }
            selObject.push(item);
        }
    }

    polyfill();//解决老旧版本兼容性问题

    var skuMapList = Object.entries(jsonData.skuMap);
    for (var i = 0; i < selObject.length; i++) {
        skuMapList = skuMapList.filter(function(item){
            return item[0].indexOf(selObject[i].value) >= 0;
        })
    }

    var result_id = null;

    if(skuMapList.length == 1) {
        result_id = skuMapList[0][1].id;
    }

    return result_id;
}

老旧版本浏览器不支持Object.entries,Object.keys,Array.filter等方法,这里polyfill()就是检测兼容性:

方法参考 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript

function polyfill(){
    if(!Object.keys){
        Object.prototype.keys = function(){
            //fun body
            ...
        }
    }

    if(!Object.entirs){
        Object.prototype.keys = function(){
            //fun body
            ...
        }
    }

    if(!Array.filter){
        Array.prototype.keys = function(){
            //fun body
            ...
        }
    }
}

最开始的算法中,找到所选规格的之后,通过拼接字符串得到skuMap的关键字。

如所选颜色color,尺寸size,那么key = color + ‘;‘ + size,最后的结果就是jsonData.skuMap[key]。

通过大量测试,发现有些情况key = size + ‘;‘ + color,导致取不到skuid。

所以改变算法,将skuMap变为列表,循环过滤。

时间: 2024-10-01 21:31:44

app接入网易严选:webview注入js的几个坑的相关文章

iOS webview注入JS

- (void)webViewDidFinishLoad:(UIWebView *)webView { NSString *js = @"function imgAutoFit() { var imgs = document.getElementsByTagName('img'); for (var i = 0; i < imgs.length; ++i) { var img = imgs[i]; img.style.maxWidth = %f; } }"; js = [NSSt

基于Node.js+MySQL开发的开源微信小程序B2C商城(页面高仿网易严选)

高仿网易严选的微信小程序商城(微信小程序客户端) 界面高仿网易严选商城(主要是2016年wap版) 测试数据采集自网易严选商城 功能和数据库参考ecshop 服务端api基于Node.js+ThinkJS+MySQL 计划添加基于Vue.js的后台管理系统.PC版.Wap版 GitHub: https://github.com/tumobi/nideshop-mini-program 项目截图 首页 专题 分类 商品列表 商品详情 购物车 订单中心 功能列表 首页 分类首页.分类商品.新品首发.

Webview动态注入js脚本

在webview加载完成后,给所有的img便签加上本地点击事件 /** 要注入的js代码 function(){ var objs = document.getElementsByTagName('img'); for(var i = 0; i <objs.length; i++) { objs[i].onclick = function() {window.toolbox.openImage(i,this.src); } }; **/ // 注入js函数监听 public void injec

WebView与Js交互

上周五,老大让暂时搞一个评分app,俩页面.第一个页面显示全部待评分的物业,第二个页面是相应物业的评分页面.评分页面是表格样式的,所以就让web端的同学写个html,我们通过Webview去展示. 这里不不过展示就完了,web页面须要知道我们点击的哪个物业以及所填评委的名字并显示在html上.所以client须要把这两个值传给html.当评委评分完后点击html里的提交button并提交成功后.client也须要进行响应.做法就是client提供接口,js代码去调用来获取值--JS调用Andro

WebView与JS的几种交互

http://www.jianshu.com/p/0042d8eb67c0 最近整理了一下原生与H5之间的交互方式,简单的做个总结.OC端与JS的交互,大致有这几种:拦截协议.JavaScriptCore库.WKWebView.自定义NSURLProtocol拦截.WebViewJavascriptBridge. JavaScriptCore一个iOS7引进的标准库,iOS7以前也有开发者自行导入使用.Web端也比较容易统一. WebViewJavascriptBridge是一个第三方库,其原理

WebView中Js与Android本地函数的相互调用

介绍 随着Html5的普及,html在表现力上不一定比原生应用差,并且有很强的扩展兼容性,所以越来越多的应用是采用Html与Android原生混合开发模式实现. 既然要实现混合开发,那么Js与Android原生函数的相互调用就必不可少了.这里写了一个demo,实现点击html中的图片进行本地展示. 原理 1.Android调用js很简单,直接webView.loadUrl("javascript:JS中的方法名称()");即可. 2.js调用Android方法,需要使用WebView.

一步一步 copy163: 网易严选 ---- vue-cli

参考 网易严选商城小程序全栈开发,域名备案中近期上线(mpvue+koa2+mysql) 小程序服务端源码地址 小程序源码地址 功能实现 api :                   ------------ 致谢 heyushuo 点这儿给个 star 吧~ 首页  https://www.heyuhsuo.xyz/heyushuo/index/index /pages/index/index.vue 专题  https://www.heyuhsuo.xyz/heyushuo/topic/l

webview与JS的交互

一:hybird app, web app 和 native app 的区别   Web App Hybird App 混合Native App 开发成本 低 中 高 维护更新 简单 简单 复杂 体验 差 优 优 跨平台 优 优 差 Native App是一种基于智能手机本地操作系统如IOS,Android等并运用原生程序编写运行的第三方运用程序,也叫本地App. Web App 是针对Iphone,Android优化后的web站点,前端使用的技术是:html5,css,javascript等,

Android WebView与JS的交互方式 最全面汇总

前言 现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 上述功能是由Android的WebView实现的,其中涉及到Android客户端与Web网页交互的实现 今天我将全面介绍Android通过WebView与JS交互的全面方式 阅读本文前请先阅读:Android开发:最全面.最易懂的Webview详解 目录 1. 交互方式总结 Android与JS通过WebView互相调用方法,实际上是: Android去调用JS的代码 JS去调用