justFeeling

just feeling only you


  • 首页

  • 归档

async和defer属性的区别-[译]

发表于 2019-12-06 | 更新于 2019-12-08

原文:https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html
目前script标签的async和defer属性已经得到不错的支持,所以是时候更详细的了解他们的具体的工作了。

图例说明

legend

纯script

首先我们来看没有定义任何属性的script标签。 HTML文件将被解析,直到脚本文件被点击为止,同时将停止解析,发起请求去提取script文件(如果是外部文件)。下载完成后将在恢复解析之前执行该脚本。
执行图

设置async的script

设置async属性会在HTML解析期间下载script文件,并在完成下载后暂停HTML解析器以执行该文件。
执行图

设置defer的script

设置defer属性会在HTML解析完成之后下载script,并在下载完成后执行该文件,同时设置了defer的脚本会按照他们在文档里面出现的顺序执行。
执行图

我们应该用哪一个?

通常我们会尽可能使用async,然后是延迟属性defer,其次才是不使用。以下是一般使用规则:

  • 如果脚本文件是独立的模块化的,且不依赖其他的脚本文件时用async;
  • 如果该脚本依赖于另一个脚本或被另一个脚本依赖,则使用defer;
  • 如果该脚本很小,并且由异步脚本所依赖,则请使用一个内联脚本,该脚本应在异步脚本上方不放置任何属性。

兼容

IE9及更低版本的defer实施中存在一些非常糟糕的错误,因此无法保证执行顺序。如果您需要兼容 <= IE9,我建议完全不要使用defer,并且如果执行顺序很重要,则使用未设置属性的script。

为什么要用语言属性(lang)?[译]

发表于 2019-11-19 | 更新于 2019-12-06

原文链接: https://www.w3.org/International/questions/qa-lang-why.en
目标读者:HTML编码人员(使用编辑器或脚本),脚本开发人员(PHP,JSP等),以及任何想知道为什么在HTML中使用(lang)语言属性的人。

提问

为什么应该在网页中使用语言属性(lang)?

语言属性(或者xml:lang)为网页内容指定相应的自然的语言。html标签上的(lang)属性会设置页面上所有文本的语言。如果页面内的一部分文本需使用其他语言,你可以给这部分内容加上标签包围并设置为相应lang值。关于如何使用lang属性请参考:HTML语言声明。

快速回答

通过识别您的网页内容的语言,可以帮您自动完成许多事情。从改变页面的外观和行为,到信息的提取以及改变应用程序的运行方式。有些语言设置会被应用到整篇文档上,有些则只会被应用到文档中某些被标记的片段上。为了能够在新的开发任务来临时获得这些好处,最好现在就为你的网页内容添加语言信息。在刚开始的时候就这么做,会比以后再进行改进要更加容易。

详细解答

在这里我们列出了目前语言信息有用的几种方式,但是,随着规范和浏览器的更新发展,将来可能会有许多其他的语言信息应用程序。

样式页面
语言属性(lang)让你可以按语言更改内容的样式。更多使用信息,请参见:使用lang属性设置样式。
例如,字体或行距可能需要更改以适应不同的字母,样式生成的引号可能需要根据语言而不同,强调样式可能需要以语言相关的方式表达,等等。
以下示例展示了如何为页面中的嵌入阿拉伯文本设置特定字体。

1
2
3
4
5
6
body {
font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif;
}
:lang(ar) {
font-family: "Traditional Arabic", "Al Bayan", serif;
}

另外一个特例则是连字符,连字符规则非常依赖于语言的。在CSS中的连字符属性的描述(在撰写本文时,浏览器才开始采用它)文中表示“正确的自动的连字符需要一直合适的连字符资源去链接被破坏的语言文本。因此,浏览器仅需要自动连接开发者设置了语言的文本(比如通过HTML的lang属性或者XML的xml:lang设置的文本),且具有自己的合适的连字符资源。”
其他受语言影响的排版和布局功能包括换行、对齐和大小写转换,以及随着规范的发展而出现的更多功能。

字体选择
浏览器可以(并且会)使用语言信息来选择适合的字体来显示,从而改善页面的整体用户体验。
比如,以统一码编码的网页,简体中文、繁体中文、日文及韩文的文字可能共用一个编码,但是这些语言的使用者希望使用的字形在每个语言的细节上都有所不同。在开发者没有明确设定字体样式的时候,一些浏览器会自动根据文本语言内容设置合适的字体样式。下图展示了在Firefox或IE等浏览器中设置不同的语言属性(lang)值的不同样式。
avatar

搜索
尽管主要搜索引擎通常使用自动语言检测来识别资源的语言,但是可以使用页面内部标记根据用户的语言偏好来提高搜索结果的质量

拼写和语法检查器
编辑器可以根据当前内容的语言调整拼写和语法检查,或者忽略不在拼写检查器语言中的内容。这可以大大提高检查拼写时的效率。
浏览器最近也开始允许用户检查他们在表单或内容可编辑元素(contenteditable)中键入的文本的拼写,考虑到有关内容语言的信息的浏览器可以提供更有效的用户体验

翻译
翻译工具可以根据设置的语言属性识别特定语言中文本的页面或部分,并自动调整工作流程或保护文本不受翻译工具中的更改。

无障碍阅读者
语言信息可帮助语音合成器和盲文翻译器产生可用的结果。这些应用程序需要知道它们是否可以从文本中产生输出,或者是否需要切换到其他语言模式。
《 W3C网站可访问性指南》建议使用语言标记,同时在某些国家的政府政策中,被强制要求使用,比如在英国-《残疾歧视法》中。

解析器和脚本
用语言信息标记内容还可以进行特定于语言的处理。
例如,脚本或XSLT样式表可用于执行各种操作,包括:
·从页面中提取特定于语言的文本
·从特定语言的页面中查找并选择信息
·按照给定语言的适当方式对内容重新排序(排序顺序非常依赖于语言)
·在转换为另一种格式(例如XSL-FO)的过程中,应用特定于文化的样式,例如适当的引号替换或强调。
请记住,创建信息时,您并不总是知道人们以后会如何处理您的信息。

顺便说一下

近年来,随着技术的进步,语言标记的用处越来越大,而且随着我们的前进,它将继续增加。在许多情况下,在第一次开发内容时,这些应用程序可能不那么重要,但随着时间的推移,它们的价值可能会增加。然而,我们目前面临着一个循环问题。没有看到语言信息应用程序的人不会提供有关其内容的语言的信息。在这些信息被广泛应用于内容之前,与语言相关的应用程序被部署得很慢。这个循环可以通过内容作者声明语言信息作为理所当然的事情来打破。标记和标记正确的内容越多,这类应用程序就会变得更有用和更普遍。添加语言信息通常很容易,不受惩罚。

storybook在vue中的基本使用

发表于 2019-11-17 | 更新于 2019-11-25

在开发过程中我们时常需要抽离很多公共组件出来,于是需要一个方式或者平台将组件以及他们的用法展示出来。
Storybook是UI组件的开发环境。它允许您浏览组件库,查看每个组件的不同状态,以及交互式开发和测试组件。
官网:https://storybook.js.org/

官方解释’故事’:

故事书是故事的集合。每个故事代表组件的单个视觉状态,技术上讲,一个故事是一个函数,它返回一些可以被渲染到屏幕上的东西。

step 1: 安装依赖

a、添加 @storybook/vue 到你的项目中

1
npm i @storybook/vue --save-dev

b、添加 @storybook相关依赖

1
2
npm install vue --save
npm install vue-loader vue-template-compiler @babel/core babel-loader babel-preset-vue --save-dev

step 2: 新增一个npm脚本

在package.json中新增一个 NPM脚本用以启动storybook

1
2
3
4
5
{
"script": {
"storybook": "start-storybook"
}
}

step 3: 创建storybook相关的配置文件

一般建议storybook配置文件夹(.storybook)放在最外层,当然你也可以放到任意你想放的位置。
对于storybook的基本配置,唯一需要做的是告诉storybook在哪里去找到故事,所以新建一个config文件,内容为

1
2
3
4
import { configure } from '@storybook/vue';

//自动引入src目录下以.stories.js结尾的所有文件
configure(require.context('../src', true, /\.stories\.js$/), module);

您可能正在使用全局组件或vue插件(例如vuex),在这种情况下,您需要在config.js文件中注册它们

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { configure } from '@storybook/vue';

import Vue from 'vue';

// Import Vue plugins
import Vuex from 'vuex';

// Import your global components.
import Mybutton from '../src/stories/Button.vue';

// Install Vue plugins.
Vue.use(Vuex);

// Register global components.
Vue.component('my-button', Mybutton);

configure(require.context('../src', true, /\.stories\.js$/), module);

上面示例注册了您的自定义Button.vue组件,安装了Vuex插件,并加载了../src/index.stories.js中定义的Storybook故事。 在调用configure()之前,应注册所有自定义组件和Vue插件

step 4: 创建你的stories

现在创建一个存放story的./stories目录,并创建你的第一个故事(stories/index.js)

CSF(Component Story Format)创建story:
1
2
3
4
5
6
7
8
9
10
import Vue from 'vue';
import MyButton from './Button.vue';

export default { title: 'Button' };
export const withText = () => '<my-button>with text</my-button>';
export const withEmoji = () => '<my-button>😀 😎 👍 💯</my-button>';
export const asAComponent = () => ({
components: { MyButton },
template: '<my-button :rounded="true">rounded</my-button>'
});
storiesOf API 创建:
1
2
3
4
5
6
7
8
9
10

import Vue from "vue";
import { storiesOf } from '@storybook/vue'
import HelloWorld from "@/components/HelloWorld.vue";

//storiesOf API 5.2以后就不建议使用
storiesOf("Hello", module).add("HelloWorld", () => ({
components: { HelloWorld },
template: `<hello-world/>`
}));

导出:将故事书导出为静态应用

Storybook附带有一个工具,可将您的Storybook导出到静态Web应用。然后可以将其部署到GitHub页面或任何静态托管服务上。
只需要简单的添加下面运行脚本

1
2
3
4
5
{
"scripts": {
"build-storybook": "build-storybook -c .storybook -o .out"
}
}

storybook常用组件使用

https://storybook.js.org/addons/

1、常用组件安装:
1
npm add -D @storybook/addons @storybook/addon-actions @storybook/addon-links @storybook/addon-notes storybook-readme

2、建立配置文件,注册插件 .storybook/addons.js:

1
2
3
4
5
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
import '@storybook/addon-notes/register';
import 'storybook-readme/register';
import '@storybook/addon-docs/register';

3、安装组件并配置参数
a、全局安装:.storybook/config.js 中通过 addDecorator(addon) 安装
b、story安装:在某个 *.stories.js 中 storiesOf(‘XXX’, module).addDecorator(addon) 安装

部分插件还需要进行参数的配置 这就会用到 addParameters() 方法
a、全局安装:.storybook/config.js 中通过 addParameters({[addonKey]: addonParam}) 追加
b、story安装:在某个 *.stories.js 中 storiesOf(‘XXX’, module).addParameters({[addonKey]: addonParam}) 追加

缺点

1、Addon太多,管理有些混乱
2、支持UI框架多,但是有的Andon却不是所有UI框架都支持,比如info,具体可参见官方文档
3、大版本之间变化大,从网上找到的示例代码比较

入门易、深耕难,StoryBook亦是如此,这需要开发人员提升组件化思维,并结合更多的实践,才能让它更好的助力前端开发。

初识flutter

发表于 2019-01-08 | 更新于 2019-12-06

flutter介绍

Flutter 是 Google推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter提供了丰富的组件、接口,开发者可以很快地为 Flutter添加 native扩展。同时 Flutter还使用 Native引擎渲染视图,这无疑能为用户提供良好的体验

官方网站:https://flutter.io/
中文网:https://flutterchina.club/
布局模型:https://flutter.dev/docs/development/ui/widgets/layout

dart语言

https://mp.weixin.qq.com/s/mtm9PKv2G_hSgbvXTbQtTA

环境安装

1
2
3
4
5
1:下载flutter sdk :https://flutter.io/docs/get-started/install
2: vscode中打开命令行 运行run flutter doctor 可看到所需要安装的环境以及已安装情况
3: 安装好所需要的安卓或者ios所需环境
4: 以xcode为例 运行:open -a Simulator 打开模拟器
(xcode的安装一不小心就会踩坑 所以建议最好直接在appStore中安装)同时安装xcode需要安装cocoapods初始化的时候注意切换ruby镜像不然跑死都跑不完

创建第一个flutter App

1
2
3
<!-- 应用主入口 -->
void main() {
}

主要知识点

flutter架构
flutter-framework

StateLessWidget?
StatefulWidget?
avatar

felx布局学习

发表于 2018-12-13

flex一直在用但是感觉理解的不够深,由于被问起,所以准备先集成一点简单的理解争取能给对方讲明白那么一丢丢~

背景

在谈flex前需要了解一下css布局 盒子模型:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model

基本概念

采用flex布局的元素称为flex容器,它的子元素是其成员,称为flex item
容器分为主轴(main axis)和交叉轴(cross axis)
借用阮一峰老师博客的一张图清晰展示了flex容器:
avatar

容器的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
flex-direction
设置主轴的方向,项目的排列方向,以主轴平行方向(row/row-reverse),或者以主轴为垂直方向(column/column-reverse)排列
flex-wrap
项目在一条主轴线上,设置其换行与否,且第二行在前还是后
flex-flow
flex-direction和flex-flow的j简写
justify-content
在主轴上的对齐方式
flex-start(默认值):左对齐
flex-end:右对齐
center: 居中
space-between:两端对齐,项目之间的间隔都相等。
space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
align-items 交叉轴上的对齐方式
flex-start:交叉轴的起点对齐。
flex-end:交叉轴的终点对齐。
center:交叉轴的中点对齐。
baseline: 项目的第一行文字的基线对齐。
stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
align-content 多轴的对齐方式

flex itme容器项目的属性

1
2
3
4
5
6
order
flex-grow
flex-shrink
flex-basis
flex
align-self

前端面试知识点架子(待更新......)

发表于 2018-09-29 | 更新于 2019-08-26

html基础

CSS基础 css3

盒子模型
BFC
css3动画
flex布局
    flex:auto/1/2
    Flex-wrap: nowrap/wrap 一行或者多行
sass/less

js基础

数组
函数
构造函数
作用域
闭包
作用域

es6

promise
箭头函数
let const
async

自动化构建项目工具的应用

webpack

node.js

计算机网络知识点

跨域解决方案
Http网络协议
  Http请求头有哪些
      Content-type

get和post的区别:
   [参考:](https://mp.weixin.qq.com/s?__biz=MzI3NzIzMzg3Mw==&mid=100000054&idx=1&sn=71f6c214f3833d9ca20b9f7dcd9d33e4#rd)

算法

冒泡排序
    当前位的值和后一位的值进行循环比较  前一位比后一位大(小)就交换它们的位置 一次循环
    双次循环实现
快排
    循环每次将最大或者最小的元素放在第一位 然后继续

前端性能优化

预加载(???),资源合并、[x]按需加载(vue chunk文件)
压缩文件gzip
    浏览器请求头设置accept-encoding:gzip
    服务器返回headers返回包含content-encoding:gzip
资源压缩合并,减少http请求
    例如雪碧图 js、css合并
非核心代码异步加载——>异步加载的方式——>异步加载的区别
 方式:1)动态脚本加载 <script>标签
    2)defer  (<script>标签上加defer或者async)
      在HTML解析完之后才会执行,如果多个,按照加载的顺序依次执行
    3)async
      在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关
利用浏览器缓存——>缓存分类——>缓存的原理
    1)强缓存
      Expires Expires:Thu,21 Jan 2017…. 过期时间
      Cache-Control Cache-Control :max-age=3600(相对时间)
    2)协商缓存
      Last-Modified If-Modified-Since Last-Modified:Web,26 Jan…..
      Etag If-None-Match
使用CDN
    静态资源分地区放在不同的服务器
预解析DNS
    <meta http-equiv=“x-dns-prefetch-control” content=“no”>
    <meta rel=“dns-prefetch” href=“//host_name_to_prefetch.com”>

设计模式 -> 观察者模式

hybird开发相关知识点

网页渲染机制

渲染机制
    什么是DOCTYPE及作用
        DTD(document type definition 文档类型定义)一系列的语法规则,告诉浏览器文档是什么类型
        DOCTYPE是用来声明文档类型和DTD规范的
    浏览器渲染过程
        HTML转成dom tree
        CSS转换成 style rules tree
        将dom tree和style rules tree转换成render tree
        layout计算位置 再绘制painting
        DOM
    重排reflow/
        增加删除修改dom节点的时候会reflow或者repaint
        移动dom位置的时候 或者加动画
        修改css样式的时候
        可能resize窗口的时候,或者滚动的时候
        修改网页默认的字体时
    重绘repaint
        dom/css改动的时候
    布局layout
Js运行机制
    单线程:同一时间只能做一件事 js是从上向下执行。 同步任务/异步任务
    同步任务优先于异步任务
    console.log(1);//同步任务
    setTimeout(function(){//异步执行 挂起
        console.log(2)
    },0);
    console.log(3);//同步任务
    输出:1 3 2

页面性能

错误监控

正则表达式基础了解

浏览器缓存机制

Vue

vue周期
Create 
    创建实例 data数据对象生成 
    Mounted 
        Vue实例挂载完成,渲染成功
    Updated
        数据变化时触动updateed方法
    Distory
        数据的变化将不再监测  dom结构依然存在
mvvm模式的理解
model view viewModel 通过双向数据绑定viewModel把view和model链接起来  数据的更新自动的 不需要人为的去干涉更新
vm层 vue做相应处理 
watch和computed的区别
组件之间的传值
通过props父组件单向传值
子组件向父组件传值
   $.emit()方法
平行组件之间的传值用vuex
vue开发中常见问题及解决方法
props只能从父组件单向传值给子组件 子组件需要改变父组件的值可以将数据设置为对象或者数组 因为引用类型的改变不会导致错误 但是官方不推荐这么做
vue源码(看不错的博客)
Q:请简要概述vue的生命周期有哪些
Q:写出vue中父子组件如何通信
Q:请输出vue-router的导航守卫(或者函数钩子)有哪些?这些函数中有哪些参数
    router.beforeEach 全局守卫
afterEach
监听路由 父组件里面 watch:{‘$route’}
Q:在vuex中,要想state中存入数据的步骤是什么
Q:Vue的get、set,里面的坑以及如何解决?
Q:Vue的批量更新?
Q:batchupdate的策略是什么?
Q:装饰器风格的vue util库怎么实现?
Q:Vue的inject和provide是什么?
Q:怎么利用Vue来实现高阶组件,slot怎么办
Q:依赖收集问题
* Vue的所有属性都是Observable的
* @computed所能自我计算的,只有他所监控的(autorun)
Q:Vue模块加载的失败处理(白屏等情况)
Q:Vue双向绑定的实现
Q:Vue diff实现(1.0,2.0),与 react diff的区别
Q:Vue如何实现的一个插件
Q:如果有多个插件怎么挂载方式便于开发
Q:如何封装一个component,在不使用template的情况下输出一下dom结构(vue)
Vue动画组件

Jquery特点和源码(找总结不错的博客看)

核心架构
事件委托
1
2
3
$(document).on("click", "td", function(){
   $(this).toggleClass("click");
   })
利用事件冒泡 做事件委托 不需要每个子元素都调用
  插件机制
  优点
    选择器id选择器的性能最高
    伪类选择器的性能最差
    链式调用速度快于非链式调用
  优化
    循环时减少对dom的操作
    e.g.:
        将dom对象定义在循环外面  或者需要插入的内容用变量存储在添加到dom中
    Dom对象的缓存

小程序web-view和网页之间的通信怎么做?token怎么存储

通常面试流程及准备

Jd描述分析
业务分析或实战模拟
技术栈准备
Jquery
Vue/react/anglur  遇到的问题 解决方法
构建工具 sass web pack npm 
自我介绍
简历
    公司岗位 技术栈职责 
    公司项目的优化方案 攻克的技术难点总结
    开源项目,github和说明 (可以参与到开源项目中)
自我陈述
    豁达、自信适度发挥
    陈述引导面试官面试自己熟悉的相关知识 
    平时喜欢逛一些不错的技术博客 看别人的总结等

技巧

模拟一面 基础
Css盒模型 dom事件类
http协议类 原型链类
面向对象类 通信类
前端安全类 前端算法类
模拟二面 项目负责人
渲染机制
Js运行机制
页面性能
错误监控
模拟三面 团队负责人
业务能力
团队协作能力
带人能力
模拟终面 hr
职业竞争力 你的优势在哪里 人家为什么要你
职业规划

题目演练

知识梳理

项目架构能力
项目把控能力

复习指导

js封装ajax请求

发表于 2017-09-21 | 更新于 2018-09-21

1.了解prototype

原型对象的作用,就是定义所有实例对象共享的属性和方法。具体理解见实际操作中

2.给String Date等对象增加继承方法

要求结果:比如var date = “2016-01-01 00:00:00”;date.format();要求输出”2016-01-01”;

1
2
3
4
5
String.prototype.format = function(){
return this.substring(0,10);
};
var str1 = "2016-01-01 00:00:00";
alert(str1.format(str1));

3.了解xmlhttprequest,能发送及接受ajax,以及分析response对象

response属性为只读,返回接收到的数据体(即body部分),他的类型可以是ArrayBuffer、Blob、Document、JSON对象、或者一个字符串。由XMLHttpRequest.responseType属性的值决定。

4.结合xmlhttprequest+prototype 自己封装一个请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
XMLHttpRequest.prototype.ajax = function(type,url,data,success,error){
var _this = this;
if(typeof data == 'object'){
var tempStr = '';
for(var key in data){
tempStr += key + '=' + data[key] + '&';
}
data = tempStr.replace(/&$/,'');
}
if(type = 'GET'){
if(data){
this.open('GET',url + '?' + data, true);
}else{
this.open('GET',url + '?version=' + Math.random(),true);
}
this.send();
}else if(type == 'POST'){
this.open('POST',url,true);
this.setRequestHeader("content-type","application/x-www-form-urlencoded");
this.send(data);
}
this.onreadystatechange = function () {
if(this.readyState == 4){
if(this.status == 200){
success(this.responseText);
}else{
if(error){
error(this.status);
}
}
}
}
};

//ajax test
var xhr = new XMLHttpRequest();
xhr.ajax('GET','/test.json',null,function(data){
alert(data);
});

html5页面js判断是否安装app,以及判断是否在app内部打开html5页面

发表于 2017-06-12 | 更新于 2018-09-21

一、html5页面js判断是否安装app

目前还不能通过浏览器直接判断是否安装app
通过谷歌参考别人的方式和测试
我们知道安装了某个app后通过scheme跳转协议(引荐:http://www.jianshu.com/p/eed01a661186)进入到app
没有安装时点击链接是无效的

所以通过点击链接后到执行进入app之间的时间差来判断是否安装app

1、下面只是处理了安卓系统时

1
2
3
4
5
6
7
8
9
10
 if (navigator.userAgent.match(/android/i) ){
var nowTime = new Date().valueOf();
setTimeout(function(){
var launchTime = new Date().valueOf() - nowTime;
if(launchTime < 28){ //28是调试估算出来的打开本地app基本需要的时间
window.location = "/phone/forward/app_download_redirect"; //下载app页面
}
},25);
window.location="mysppscheme://";//自己定义的scheme协议
}

2、iphone用一样的原理实现测试有效

3、weixin分享里面的页面会在url添加变量isappinstalled

isappinstalled=1的时候代表安装了app,值为0的时候代表没有安装
微信屏蔽了url scheme直接跳转,所以weixin分享页通过提示浏览器打开
再根据之前的isappubstalled值来判断是否安装app

1
2
var isWeixin = navigator.userAgent.match(/MicroMessenger/ig);  //是否在微信
var appInstalled = document.location.href.indexOf("isappinstalled=1")>=0; //是否安装app

上面方式是我通过谷歌看大家提出的方式和自己的测试唯一还没出现问题的方式
当然后续有问题会继续更新

二、判断是否在app内部打开html5页面

判断当前页面是否在app内部打开,单纯的web前端还不能解决
需要客户端对userAgent添加自己app相关的字段
(useragent设置Android:http://www.jincon.com/archives/354/)
(useragent设置IOS:http://www.jianshu.com/p/5f02451b8e87)

1
2
var userAgent = navigator.userAgent.toLowerCase(), //获取userAgent
isInapp = userAgent.indexOf("sunyuki")>=0;//查询是否有相关app的相关字段

feeling

8 日志
© 2019 feeling
由 Hexo 强力驱动 v3.7.1
|
主题 – NexT.Muse v6.4.1