通用
字体文件使用
文件字体
- 下载 ttf 字体文件
在 style 中引入
@font-face { font-family: "Impact"; src: url('~@/static/iconfont/IMPACT.TTF'); } .item { font-family: Impact }
字体图标
推荐在线预览 icon 图标文件
在 style 中引入
@font-face { font-family: "iconfont"; src: url('~@/static/iconttf/ali.ttf') } .iconfont { font-family:"iconfont" !important; font-size:32upx; font-style:normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon-notice:before { content: "\e64f"; }
html中直接使用
class="iconfont icon-notice"
好用的组件
树组件
支持懒加载;支持单选/多选;支持搜索;支持禁用/默认选中;支持手风琴;支持高亮(仿 element-ui tree)
subNVue
subNvue,是 vue 页面的原生子窗体,把weex渲染的原生界面当做 vue 页面的子窗体覆盖在页面上。它不是全屏页面,它给App平台vue页面中的层级覆盖和原生界面自定义提供了更强大和灵活的解决方案。它也不是组件,就是一个原生子窗体。
富文本(rich-text)
在 uniapp 中使用 nvue页面编写,需要处理 后端返回的富文本内容的时候,想到用次 组件。
注意点:
nodes 值为 HTML String 时,在组件内部将自动解析为节点列表,推荐直接使用 Array
类型避免内部转换导致的性能下降。App-nvue 和支付宝小程序不支持 HTML String 方式,仅支持直接使用节点列表即 Array 类型,如要使用 HTML String,则需自己将 HTML String 转化为 nodes 数组,可使用 html-parser
转换。
Tips
- nodes 不推荐使用 String 类型,性能会有所下降。
- rich-text 组件内屏蔽所有节点的事件。所以如果内容中有链接、图片需要点击,则不能使用rich-text,此时可在uni-app插件市场 (opens new window)搜索parse插件使用。app-nvue的rich-text组件支持链接图片点击
- attrs 属性不支持 id ,支持 class 。
- name 属性大小写不敏感。
- 如果使用了不受信任的HTML节点,该节点及其所有子节点将会被移除。
- 非 App 平台 img 标签仅支持网络图片。
- 如果在自定义组件中使用 rich-text 组件,那么仅自定义组件的 css 样式对 rich-text 中的 class 生效。
- 使用 itemclick 时,如果发生节点嵌套,外层 a标签 优先级高。
// html-parser.js
// Regular Expressions for parsing tags and attributes
var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
// fixed by xxx 将 ins 标签从块级名单中移除
var block = makeMap('a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video'); // Inline Elements - HTML 5
var inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'); // Elements that you can, intentionally, leave open
// (and which close themselves)
var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); // Attributes that have their values filled in disabled="disabled"
var fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'); // Special Elements (can contain anything)
var special = makeMap('script,style');
function HTMLParser(html, handler) {
var index;
var chars;
var match;
var stack = [];
var last = html;
stack.last = function () {
return this[this.length - 1];
};
while (html) {
chars = true; // Make sure we're not in a script or style element
if (!stack.last() || !special[stack.last()]) {
// Comment
if (html.indexOf('<!--') == 0) {
index = html.indexOf('-->');
if (index >= 0) {
if (handler.comment) {
handler.comment(html.substring(4, index));
}
html = html.substring(index + 3);
chars = false;
} // end tag
} else if (html.indexOf('</') == 0) {
match = html.match(endTag);
if (match) {
html = html.substring(match[0].length);
match[0].replace(endTag, parseEndTag);
chars = false;
} // start tag
} else if (html.indexOf('<') == 0) {
match = html.match(startTag);
if (match) {
html = html.substring(match[0].length);
match[0].replace(startTag, parseStartTag);
chars = false;
}
}
if (chars) {
index = html.indexOf('<');
var text = index < 0 ? html : html.substring(0, index);
html = index < 0 ? '' : html.substring(index);
if (handler.chars) {
handler.chars(text);
}
}
} else {
html = html.replace(new RegExp('([\\s\\S]*?)<\/' + stack.last() + '[^>]*>'), function (all, text) {
text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, '$1$2');
if (handler.chars) {
handler.chars(text);
}
return '';
});
parseEndTag('', stack.last());
}
if (html == last) {
throw 'Parse Error: ' + html;
}
last = html;
} // Clean up any remaining tags
parseEndTag();
function parseStartTag(tag, tagName, rest, unary) {
tagName = tagName.toLowerCase();
if (block[tagName]) {
while (stack.last() && inline[stack.last()]) {
parseEndTag('', stack.last());
}
}
if (closeSelf[tagName] && stack.last() == tagName) {
parseEndTag('', tagName);
}
unary = empty[tagName] || !!unary;
if (!unary) {
stack.push(tagName);
}
if (handler.start) {
var attrs = [];
rest.replace(attr, function (match, name) {
var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : fillAttrs[name] ? name : '';
attrs.push({
name: name,
value: value,
escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') // "
});
});
if (handler.start) {
handler.start(tagName, attrs, unary);
}
}
}
function parseEndTag(tag, tagName) {
// If no tag name is provided, clean shop
if (!tagName) {
var pos = 0;
} // Find the closest opened tag of the same type
else {
for (var pos = stack.length - 1; pos >= 0; pos--) {
if (stack[pos] == tagName) {
break;
}
}
}
if (pos >= 0) {
// Close all the open elements, up the stack
for (var i = stack.length - 1; i >= pos; i--) {
if (handler.end) {
handler.end(stack[i]);
}
} // Remove the open elements from the stack
stack.length = pos;
}
}
}
function makeMap(str) {
var obj = {};
var items = str.split(',');
for (var i = 0; i < items.length; i++) {
obj[items[i]] = true;
}
return obj;
}
function removeDOCTYPE(html) {
return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
}
function parseAttrs(attrs) {
return attrs.reduce(function (pre, attr) {
var value = attr.value;
var name = attr.name;
if (pre[name]) {
pre[name] = pre[name] + " " + value;
} else {
pre[name] = value;
}
return pre;
}, {});
}
function parseHtml(html) {
html = removeDOCTYPE(html);
var stacks = [];
var results = {
node: 'root',
children: []
};
HTMLParser(html, {
start: function start(tag, attrs, unary) {
var node = {
name: tag
};
if (attrs.length !== 0) {
node.attrs = parseAttrs(attrs);
}
if (unary) {
var parent = stacks[0] || results;
if (!parent.children) {
parent.children = [];
}
parent.children.push(node);
} else {
stacks.unshift(node);
}
},
end: function end(tag) {
var node = stacks.shift();
if (node.name !== tag) console.error('invalid state: mismatch end tag');
if (stacks.length === 0) {
results.children.push(node);
} else {
var parent = stacks[0];
if (!parent.children) {
parent.children = [];
}
parent.children.push(node);
}
},
chars: function chars(text) {
var node = {
type: 'text',
text: text
};
if (stacks.length === 0) {
results.children.push(node);
} else {
var parent = stacks[0];
if (!parent.children) {
parent.children = [];
}
parent.children.push(node);
}
},
comment: function comment(text) {
var node = {
node: 'comment',
text: text
};
var parent = stacks[0];
if (!parent.children) {
parent.children = [];
}
parent.children.push(node);
}
});
return results.children;
}
export default parseHtml;
// 使用范例
import htmlParser from '@/common/lib/html-parser.js';
const nodes = htmlParser('<p>兑换规则</p>');
// html
<rich-text :nodes="nodes"></rich-text>
uniapp修改导航栏按钮文本及样式 app端及h5端
h5端:需使用Dom操作修改
- 按钮样式修改 ```js document.querySelector('.uni-page-head .uni-page-head-ft .uni-page-head-btn').setAttribute("style","background-color:transparent;width:auto;")
2. 按钮文本修改
```js
document.querySelectorAll('.uni-page-head .uni-page-head-ft .uni-page-head-btn')[1].querySelector('.uni-btn-icon').innerText='按钮文本';
// 注:[1]为按钮index
app端:使用:
var webView = this.$mp.page.$getAppWebview();
webView.setTitleNViewButtonStyle(0,{
width: 'auto',
text: "新增协议",
fontSize: '14px'
});
uniapp中跳转第三方浏览器下载app
- plus.runtime.openURL(url)
- 不能使用 plus.runtime.openWeb(url),会导致下载完得apk,无法解析安装
uniapp使用webvie应用html页面时,返回有找不到页面情况
<script>
var wv; //计划创建的webview
export default {
data() {
return {
data: {},
}
},
onLoad(e) {
const uuid = uni.getStorageSync('uuid');
const token = uni.getStorageSync('token');
this.data.userId = uni.getStorageSync('userId');
this.data.url = this.$baseurl;
this.data.uuid = uuid;
this.data.token = token;
// #ifdef APP-PLUS
wv = plus.webview.create("", "custom-webview", {
plusrequire: "none", //禁止远程网页使用plus的API,有些使用mui制作的网页可能会监听plus.key,造成关闭页面混乱,可以通过这种方式禁止
'uni-app': 'none', //不加载uni-app渲染层框架,避免样式冲突
top: uni.getSystemInfoSync().statusBarHeight + 44 //放置在titleNView下方。如果还想在webview上方加个地址栏的什么的,可以继续降低TOP值
})
wv.loadURL(`/hybrid/html/webView.html?data=${JSON.stringify(this.data)}`)
var currentWebview = this.$scope
.$getAppWebview(); //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
currentWebview.append(wv); //一定要append到当前的页面里!!!才能跟随当前页面一起做动画,一起关闭
setTimeout(function() {
console.log(wv.getStyle())
}, 1000); //如果是首页的onload调用时需要延时一下,二级页面无需延时,可直接获取
// #endif
}
};
</script>