提交 01d10610 编写于 作者: D DCloud_LXH

update: 菜单更新 第一版

上级 aadaf501
dist
\ No newline at end of file
const { slugify } = require('@vuepress/shared-utils')
const translatePlugin = require('./markdown/translate')
const headerPlugin = require('./markdown/header')
const createSidebar = require('./markdown/createSidebar')
const tabs = ['/uniCloud/', '/plugin/', '/worktile/', '/tutorial/', '/collocation/', '/component/', '/api/', '/']
const config = {
// base: '/docs/',
// TODO use theme
title: 'uni-app',
themeConfig: {
titleLogo: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/1ae87107-2943-4ba6-be2b-390ca27c6260.png',
logo: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/5a7f902b-21a7-4822-884f-925219eacc4b.png',
// TODO use plugin/theme
sidebar: createSidebar(tabs),
// sidebarDepth: 2,
nextLinks: false,
prevLinks: false,
// TODO use theme
repo: 'dcloudio/uni-app',
docsRepo: 'dcloudio/unidocs-en',
docsBranch: 'main',
docsDir: 'docs',
editLinks: true,
editLinkText: '帮助我们改善此页面!',
// smoothScroll: true,
algolia: {
apiKey: 'ca67b01d14df58783e2f7dc45c79736e',
indexName: 'en-uniapp-dcloud',
appId: 'TZ0EGQ9J1Y'
}
},
markdown: {
slugify(str) {
let slug = str
if (slug.includes('@')) {
let array = slug.split('@')
slug = array.length > 1 ? array[array.length - 1] : str
} else {
const UNI = 'uni.'
if (slug.startsWith(UNI)) {
slug = slug.split(UNI)[1]
}
if (slug.indexOf('OBJECT') !== -1) {
['(', ''].forEach(item => {
if (slug.indexOf(item) !== -1)
slug = slug.split(item)[0].toLocaleLowerCase();
})
}
}
return slugify(slug)
},
extractHeaders: ['h1', 'h2', 'h3', 'h4'],
chainMarkdown(config) {
config
.plugin('translate')
.use(translatePlugin)
.end()
.plugin('convert-header')
.use(headerPlugin)
}
}
}
module.exports = config
\ No newline at end of file
function createMarkdownArray(contents = [], childrenName = 'children') {
const markdownArray = []
let itemCatch = {}
for (let index = 0; index < contents.length; index++) {
const item = contents[index];
if (itemCatch.parent) {
if (item.level === itemCatch.level) {
const child = {
...item,
parent: itemCatch.parent
};
itemCatch.parent[childrenName].push(child)
delete itemCatch.parent
itemCatch = child
continue
} else if (item.level > itemCatch.level) {
const child = {
...item,
parent: itemCatch
};
(itemCatch[childrenName] || (itemCatch[childrenName] = [])).push(child)
itemCatch = child
} else {
const parent = itemCatch.parent
delete itemCatch.parent
itemCatch = parent
index--
continue
}
} else {
if (typeof itemCatch.level === 'undefined' || item.level === itemCatch.level) {
itemCatch = item
markdownArray.push(itemCatch)
} else {
const child = {
...item,
parent: itemCatch
};
(itemCatch[childrenName] || (itemCatch[childrenName] = [])).push(child)
itemCatch = child
continue
}
}
}
function removeParent(childs = []) {
childs.forEach(child => {
if (child.parent) delete child.parent
if (child[childrenName]) removeParent(child[childrenName])
})
}
// 移除最后一项 parent 节点,防止循环引用报错
removeParent(markdownArray[markdownArray.length - 1][childrenName])
return markdownArray
}
module.exports = createMarkdownArray
\ No newline at end of file
const fs = require('fs')
const path = require('path')
const MarkdownIt = require('markdown-it');
const createMarkdownArray = require('./createMarkdownArray')
const { isExternal } = require('../utils')
function parseBar(file, options) {
const textName = options.text || 'text'
const linkName = options.link || 'link'
const contents = []
new MarkdownIt()
.parse(fs.readFileSync(file, { encoding: 'utf-8' }))
.forEach(token => {
if (token.type === 'inline') {
let [_, text, link] = token.content.match(/\[(.+?)\]\((.+?)\)/) || token.content.match(/(.+)/)
link = link && (
isExternal(link)
? link
: path.join('/', link.replace(/\.md\b/, '')
.replace(/\bREADME\b/, '')
.replace(/\/index/, '/')
.replace(/\?id=/, '#'))
.replace(/\\/g, '/')
)
contents.push({
level: token.level,
[textName]: text,
[linkName]: link
})
}
})
return createMarkdownArray(contents, options.children)
}
module.exports = function (tabs = []) {
const sidebar = {}
tabs.forEach(tab => {
sidebar[tab] = parseBar(path.join(__dirname, '../../', tab, '_sidebar.md'), {
text: 'title',
link: 'path'
})
})
return tabs.length ? sidebar : false
}
\ No newline at end of file
function parseHeader(tokens) {
tokens.forEach((t, i) => {
if (t.type === 'heading_open' && /h\d/.test(t.tag)) {
const token = tokens[i + 1]
const title = token.content
const res = title.match(/\s*(.+?)@(.+?)\s*$/)
if (res) {
token.content = res[1]
for (let i = 0, array = token.children, l = array.length; i < l; i++) {
const token = array[l - 1 - i]
if (token.type === 'text') {
const title = token.content
const res = title.match(/(.*)@.+/)
if (res) {
token.content = res[1]
break
}
}
}
}
}
})
return tokens
}
module.exports = md => {
md.parse = (function (mdParse) {
return function (src, ...array) {
return parseHeader(mdParse.bind(this)(src, ...array))
}
})(md.parse)
}
/**
* text
* target
* link // 有协议时是外链
* items
* type // link、links。
* rel
*/
export const navbar = [
{
text: 'uni-app',
items: [
{
text: '介绍',
type: 'link',
link: '/'
},
{
text: '教程',
type: 'link',
link: '/tutorial/'
},
{
text: '全局文件',
type: 'link',
link: '/collocation/pages'
},
{
text: '组件',
type: 'link',
link: '/component/'
},
{
text: 'API',
type: 'link',
link: '/api/'
},
{
text: '插件',
type: 'link',
link: '/plugin/'
},
{
text: '工程化',
type: 'link',
link: '/worktile/'
},
{
text: '其他规范',
type: 'links',
link: 'http://www.html5plus.org/doc/h5p.html',
items: [
{
text: 'App扩展规范 HTML5 Plus',
type: 'link',
link: 'http://www.html5plus.org/doc/h5p.html'
},
{
text: '微信小程序',
type: 'link',
link: 'https://developers.weixin.qq.com/miniprogram/dev/framework/'
},
{
text: '支付宝小程序',
type: 'link',
link: 'https://docs.alipay.com/mini/developer/getting-started'
},
{
text: '百度小程序',
type: 'link',
link: 'https://smartprogram.baidu.com/docs/develop/tutorial/codedir/'
},
{
text: '字节跳动小程序',
type: 'link',
link: 'https://developer.toutiao.com/dev/cn/mini-app/develop/component/introduction/basic-component'
},
{
text: '飞书小程序',
type: 'link',
link: 'https://open.feishu.cn/document/uYjL24iN/uUDNzUjL1QzM14SN0MTN'
},
{
text: '钉钉小程序',
type: 'link',
link: 'https://developers.dingtalk.com/document/app/introduction-to-dingtalk-mini-programs'
},
{
text: 'QQ小程序',
type: 'link',
link: 'https://q.qq.com/wiki/develop/miniprogram/frame/'
},
{
text: '快手小程序',
type: 'link',
link: 'https://mp.kuaishou.com/docs/develop/frame/config/conf_appjson.html'
},
{
text: '华为快应用',
type: 'link',
link: 'https://developer.huawei.com/consumer/cn/doc/development/quickApp-References/webview-component-view'
},
{
text: '360小程序',
type: 'link',
link: 'https://mp.360.cn/doc/miniprogram/dev/#/view'
},
{
text: 'Weex',
type: 'link',
link: 'http://doc.weex.io/zh/guide/introduction.html'
},
]
},
{
link: "https://github.com/dcloudio/uni-app",
target: "_blank",
text: "GitHub",
type: "link"
}
]
},
{
text: 'uniCloud',
type: 'link',
link: '/uniCloud/'
},
{
text: 'HBuilder',
link: 'https://www.dcloud.io/hbuilderx.html',
type: "link",
target: '_blank',
needOutbound: false
},
{
text: 'uni 小程序 sdk',
link: 'https://nativesupport.dcloud.net.cn/UniMPDocs/SDKDownload/android',
type: "link",
target: '_blank',
needOutbound: false
},
/* {
text: '问答社区',
link: 'https://ask.dcloud.net.cn/explore/',
type: "link",
target: '_blank',
needOutbound: false
},
{
text: '插件市场',
type: "link",
target: '_blank',
link: 'https://ext.dcloud.net.cn/',
needOutbound: false
} */
]
\ No newline at end of file
module.exports = md => {
md.parse = (function (mdParse) {
return function (src, ...array) {
return mdParse.bind(this)(src, ...array)
}
})(md.parse)
md.render = (function (mdRender) {
return function (src, ...array) {
return mdRender.bind(this)(src, ...array)
}
})(md.render)
}
<template>
<div
v-if="show"
class="main-navbar-link"
>
<DropdownLink
v-if="item.type === 'links'"
:item="item"
/>
<NavLink
v-else
:item="item"
/>
</div>
</template>
<script>
import DropdownLink from '@theme/components/DropdownLink.vue'
import NavLink from '@theme/components/NavLink.vue'
export default {
name: 'MainNavbarLink',
components: {
DropdownLink,
NavLink
},
props: {
item: {
type: Object,
default: () => ({})
}
},
computed: {
show() {
return this.item.type === 'link'
? this.item.link
: this.item.type === 'links'
? !!this.item.items.length
: false
}
}
}
</script>
<style lang="stylus" scope>
.main-navbar-link a
color inherit
@media (max-width: $MQMobile)
ul
list-style none
a
padding-top 0 !important
</style>
\ No newline at end of file
<template>
<RouterLink
v-if="isInternal"
class="nav-link"
:to="link"
:exact="exact"
@focusout.native="focusoutAction"
>
{{ item.text }}
</RouterLink>
<a
v-else
:href="link"
class="nav-link external"
:target="target"
:rel="rel"
@focusout="focusoutAction"
>
{{ item.text }}
<OutboundLink v-if="item.needOutbound !== false && isBlankTarget" />
</a>
</template>
<script>
import { isExternal, isMailto, isTel, ensureExt } from '../util'
export default {
name: 'NavLink',
inject: [ 'customNavBar' ],
props: {
item: {
required: true
}
},
computed: {
link () {
return ensureExt(this.item.link)
},
exact () {
if (this.$site.locales) {
return Object.keys(this.$site.locales).some(rootLink => rootLink === this.link)
}
return this.link === '/'
},
isNonHttpURI () {
return isMailto(this.link) || isTel(this.link)
},
isBlankTarget () {
return this.target === '_blank'
},
isInternal () {
return !isExternal(this.link) && !this.isBlankTarget
},
target () {
if (this.isNonHttpURI) {
return null
}
if (this.item.target) {
return this.item.target
}
return isExternal(this.link) ? '_blank' : ''
},
rel () {
if (this.isNonHttpURI) {
return null
}
if (this.item.rel === false) {
return null
}
if (this.item.rel) {
return this.item.rel
}
return this.isBlankTarget ? 'noopener noreferrer' : null
}
},
methods: {
focusoutAction () {
this.$emit('focusout')
}
}
}
</script>
<template>
<nav
v-if="(userLinks.length || repoLink) && showSubNavBar"
class="nav-links"
>
<!-- user links -->
<div
v-for="item in userLinks"
:key="item.link"
class="nav-item"
>
<DropdownLink
v-if="item.type === 'links'"
:item="item"
/>
<NavLink
v-else
:item="item"
/>
</div>
<!-- repo link -->
<!-- <a
v-if="repoLink"
:href="repoLink"
class="repo-link"
target="_blank"
rel="noopener noreferrer"
>
{{ repoLabel }}
<OutboundLink />
</a> -->
</nav>
</template>
<script>
import DropdownLink from '@theme/components/DropdownLink.vue'
import { resolveNavLinkItem } from '../util'
import NavLink from '@theme/components/NavLink.vue'
import navInject from '../mixin/navInject';
export default {
name: 'NavLinks',
mixins: [ navInject ],
components: {
NavLink,
DropdownLink
},
computed: {
userNav () {
return this.customNavBar[this.navConfig.userNavIndex].items || []
// return this.$themeLocaleConfig.nav || this.$site.themeConfig.nav || []
},
nav () {
const { locales } = this.$site
if (locales && Object.keys(locales).length > 1) {
const currentLink = this.$page.path
const routes = this.$router.options.routes
const themeLocales = this.$site.themeConfig.locales || {}
const languageDropdown = {
text: this.$themeLocaleConfig.selectText || 'Languages',
ariaLabel: this.$themeLocaleConfig.ariaLabel || 'Select language',
items: Object.keys(locales).map(path => {
const locale = locales[path]
const text = themeLocales[path] && themeLocales[path].label || locale.lang
let link
// Stay on the current page
if (locale.lang === this.$lang) {
link = currentLink
} else {
// Try to stay on the same page
link = currentLink.replace(this.$localeConfig.path, path)
// fallback to homepage
if (!routes.some(route => route.path === link)) {
link = path
}
}
return { text, link }
})
}
return [...this.userNav, languageDropdown]
}
return this.userNav
},
userLinks () {
return (this.nav || []).map(link => {
return Object.assign(resolveNavLinkItem(link), {
items: (link.items || []).map(resolveNavLinkItem)
})
})
},
repoLink () {
const { repo } = this.$site.themeConfig
if (repo) {
return /^https?:/.test(repo)
? repo
: `https://github.com/${repo}`
}
return null
},
repoLabel () {
if (!this.repoLink) return
if (this.$site.themeConfig.repoLabel) {
return this.$site.themeConfig.repoLabel
}
const repoHost = this.repoLink.match(/^https?:\/\/[^/]+/)[0]
const platforms = ['GitHub', 'GitLab', 'Bitbucket']
for (let i = 0; i < platforms.length; i++) {
const platform = platforms[i]
if (new RegExp(platform, 'i').test(repoHost)) {
return platform
}
}
return 'Source'
}
}
}
</script>
<style lang="stylus">
.nav-links
display inline-block
a
line-height 1.4rem
color inherit
&:hover, &.router-link-active
color $accentColor
.nav-item
position relative
display inline-block
margin-left 1.5rem
line-height 2rem
&:first-child
margin-left 0
.repo-link
margin-left 1.5rem
@media (max-width: $MQMobile)
.nav-links
.nav-item, .repo-link
margin-left 0
@media (min-width: $MQMobile)
.nav-item > .nav-link:not(.external)
display block
height 40px
line-height 40px
min-width 24px
padding 0 2vw
background-color #fff
border-radius 4px
transition background .3s
font-size 14px
/* .nav-links a
&:hover, &.router-link-active
color $textColor*/
.nav-item > a:not(.external)
&:hover
background-color #f0f0f0
&.router-link-active
color #fff
background-color $accentColor
</style>
<template>
<header class="navbar" :class="{ 'navbar-fixed': fixedNavbar }">
<div class="main-navbar">
<!-- <SidebarButton @toggle-sidebar="$emit('toggle-sidebar')" /> -->
<RouterLink
:to="$localePath"
class="home-link"
>
<img
v-if="$site.themeConfig.logo"
class="logo"
:src="$withBase($site.themeConfig.logo)"
:alt="$siteTitle"
>
<img
v-if="$site.themeConfig.titleLogo"
class="title-logo can-hide"
:src="$withBase($site.themeConfig.titleLogo)"
:alt="$siteTitle"
>
<span
v-else-if="$siteTitle"
ref="siteName"
class="site-name"
:class="{ 'can-hide': $site.themeConfig.logo }"
>{{ $siteTitle }}</span>
</RouterLink>
<div class="main-navbar-links can-hide">
<template v-for="(item, index) in customNavBar">
<div :class="mainNavLinkClass(index)" :key="item.text">
<MainNavbarLink v-if="item.type" :item='item' />
<a v-else href="javascript:;" @click="changeUserNav(index)">{{item.text}}</a>
</div>
</template>
</div>
<div class="mobile-main-navbar">
<div class="mobile-links_mobile">
<a href="javascript:;" class="mobile-links__btn" @click="toggleMobilePanel">{{mainNavBarText}}</a>
</div>
<div class="mobile-links__panel" :class="{open: showMobilePanel}">
<template v-for="(item, index) in customNavBar">
<div :class="mainNavLinkClass(index)" :key="item.text">
<MainNavbarLink v-if="item.type" :item='item' @click.native="toggleMobilePanel"/>
<a v-else href="javascript:;" @click="changeUserNav(index),toggleMobilePanel()">{{item.text}}</a>
</div>
</template>
</div>
</div>
<div
class="links"
:style="linksWrapMaxWidth ? {
'max-width': linksWrapMaxWidth + 'px'
} : {}"
>
<AlgoliaSearchBox
v-if="isAlgoliaSearch"
:options="algolia"
/>
<SearchBox v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false" />
</div>
</div>
<div class="sub-navbar">
<NavLinks class="can-hide" />
<div class="mobile-sub-navbar">
<div class="subnavbar__item" @click="$emit('toggle-sidebar')">
<a href="javascript:;">{{subNavBarText}}</a>
</div>
</div>
</div>
</header>
</template>
<script>
import AlgoliaSearchBox from '@AlgoliaSearchBox'
import SearchBox from '@SearchBox'
import SidebarButton from '@theme/components/SidebarButton.vue'
import NavLinks from '@theme/components/NavLinks.vue'
import MainNavbarLink from './MainNavbarLink.vue';
import navInject from '../mixin/navInject';
import { forbidScroll, os } from '../util';
export default {
name: 'Navbar',
mixins: [ navInject ],
components: {
SidebarButton,
NavLinks,
MainNavbarLink,
SearchBox,
AlgoliaSearchBox
},
data () {
return {
linksWrapMaxWidth: null,
showMobilePanel: false,
fixedNavbar: false
}
},
computed: {
algolia () {
return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
},
isAlgoliaSearch () {
return this.algolia && this.algolia.apiKey && this.algolia.indexName
}
},
mounted () {
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight'))
const handleLinksWrapWidth = () => {
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
this.linksWrapMaxWidth = null
} else {
this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING
- (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0)
}
this.$nextTick(this.initNavBar)
}
handleLinksWrapWidth()
window.addEventListener('resize', handleLinksWrapWidth, false)
this.initNavBar()
},
methods: {
initNavBar () {
os.init()
this.sideBar = document.querySelector('.sidebar')
this.navbar = document.querySelector('.navbar')
this.mainNavBar = document.querySelector('.main-navbar')
this.subNavBar = document.querySelector('.sub-navbar')
this.pageContainer = document.querySelector('.page')
this.navbarHeight = this.navbar.clientHeight
this.subNavBarHeight = this.subNavBar.clientHeight
this.mainNavBarHeight = this.mainNavBar.clientHeight
this.removeWindowScroll()
if (os.pc) {
this.onWindowScroll()
window.addEventListener('scroll', this.onWindowScroll, false)
}
},
removeWindowScroll () {
window.removeEventListener('scroll', this.onWindowScroll)
this.fixedNavbar = false
this.sideBar && this.sideBar.removeAttribute('style')
this.navbar && this.navbar.removeAttribute('style')
this.pageContainer && this.pageContainer.removeAttribute('style')
},
onWindowScroll () {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
{
let sideTop = this.navbarHeight - scrollTop
sideTop <= this.subNavBarHeight && (sideTop = this.subNavBarHeight)
this.sideBar && (this.sideBar.style.top = `${sideTop}px`)
}
if (scrollTop >= this.mainNavBarHeight) {
if (!this.fixedNavbar) {
this.fixedNavbar = true
this.navbar.style.top = `-${this.mainNavBarHeight}px`
this.$nextTick(() => {
this.pageContainer && (this.pageContainer.style.marginTop = `${this.navbarHeight}px`)
})
}
} else if (scrollTop < this.mainNavBarHeight) {
if (this.fixedNavbar) {
this.fixedNavbar = false
this.pageContainer && this.pageContainer.removeAttribute('style')
}
}
},
mainNavLinkClass (index) {
return ['main-navbar-item', this.navConfig.userNavIndex === index ? 'active' : '']
},
toggleMobilePanel () {
this.showMobilePanel = !this.showMobilePanel
forbidScroll(this.showMobilePanel)
}
},
watch: {
'navConfig.userNavIndex' () {
this.$nextTick(()=>{
if(!os.pc) return
this.navbarHeight = this.navbar.clientHeight
this.subNavBarHeight = this.subNavBar.clientHeight
this.sideBar.style.top = `${this.navbarHeight}px`
})
}
}
}
function css (el, property) {
// NOTE: Known bug, will return 'auto' if style value is 'auto'
const win = el.ownerDocument.defaultView
// null means not to return pseudo styles
return win.getComputedStyle(el, null)[property]
}
</script>
<style lang="stylus">
$navbar-vertical-padding = 0.7rem
$navbar-horizontal-padding = 1.5rem
@import '../styles/navbar'
.navbar
// padding $navbar-vertical-padding $navbar-horizontal-padding
line-height $navbar-main-navbar-height // $navbarHeight - 1.4rem
a, span, img
display inline-block
.title-logo
.logo
height $navbar-logo-height // $navbarHeight - 1.4rem
min-width $navbar-main-navbar-height // $navbarHeight - 1.4rem
margin-right 0.8rem
vertical-align top
.site-name
font-size 1.3rem
font-weight 600
color $textColor
position relative
.links
padding-left 1.5rem
box-sizing border-box
background-color white
white-space nowrap
font-size 0.9rem
position absolute
right $navbar-horizontal-padding
top 0 //$navbar-vertical-padding
display flex
.search-box
flex: 0 0 auto
vertical-align top
@media (max-width: $MQMobile)
.navbar
// padding-left 4rem
.can-hide
display none !important
.links
padding-left 0rem // 1.5rem
.site-name
width calc(100vw - 9.4rem)
overflow hidden
white-space nowrap
text-overflow ellipsis
</style>
<script>
import { isActive, hashRE, groupHeaders } from '../util'
export default {
functional: true,
props: ['item', 'sidebarDepth'],
render (h,
{
parent: {
$page,
$site,
$route,
$themeConfig,
$themeLocaleConfig
},
props: {
item,
sidebarDepth
}
}) {
// use custom active class matching logic
// due to edge case of paths ending with / + hash
const selfActive = isActive($route, item.path)
const maxDepth = [
$page.frontmatter.sidebarDepth,
sidebarDepth,
$themeLocaleConfig.sidebarDepth,
$themeConfig.sidebarDepth,
1
].find(depth => depth !== undefined)
// for sidebar: auto pages, a hash link should be active if one of its child
// matches
const active = item.type === 'auto'
? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug))
: selfActive
const link = item.type === 'external'
? renderExternal(h, item.path, item.title || item.path)
: renderLink(h, item.path, item.title || item.path, active, undefined, item.headers)
const displayAllHeaders = $themeLocaleConfig.displayAllHeaders
|| $themeConfig.displayAllHeaders
if (item.type === 'auto') {
return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)]
} else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) {
const children = groupHeaders(item.headers)
return [link, renderChildren(h, children, item.path, $route, maxDepth)]
} else {
return link
}
}
}
function renderLink (h, to, text, active, level, headers) {
const component = {
props: {
to,
activeClass: '',
exactActiveClass: ''
},
class: {
active,
'sidebar-link': true,
'data-no-emphasize': headers && headers.some(item => item.level < 3)
}
}
if (level > 2) {
component.style = {
'padding-left': level + 'rem'
}
}
return h('RouterLink', component, text)
}
function renderChildren (h, children, path, route, maxDepth, depth = 1) {
if (!children || depth > maxDepth) return null
return h('ul', { class: 'sidebar-sub-headers' }, children.map(c => {
const active = isActive(route, path + '#' + c.slug)
return h('li', { class: 'sidebar-sub-header' }, [
renderLink(h, path + '#' + c.slug, c.title, active, c.level - 1),
renderChildren(h, c.children, path, route, maxDepth, depth + 1)
])
}))
}
function renderExternal (h, to, text) {
return h('a', {
attrs: {
href: to,
target: '_blank',
rel: 'noopener noreferrer'
},
class: {
'sidebar-link': true
}
}, [text, h('OutboundLink')])
}
</script>
<style lang="stylus">
.sidebar .sidebar-sub-headers
padding-left 1rem
font-size 0.95em
a.sidebar-link
font-size 1em
font-weight 400
display inline-block
color $textColor
border-left 0.25rem solid transparent
padding 0.35rem 1rem 0.35rem 1.25rem
line-height 1.4
width: 100%
box-sizing: border-box
&:hover
color $accentColor
&.active
font-weight 600
color $accentColor
border-left-color $accentColor
.sidebar-group &
padding-left 2rem
.sidebar-sub-headers &
padding-top 0.25rem
padding-bottom 0.25rem
border-left none
&.active
font-weight 500
</style>
\ No newline at end of file
function handleRedirectForCleanUrls(router, to) {
if (isRouteExists(router, to.path)) {
return to.path
} else {
if (!/(\/|\.html)$/.test(to.path)) {
const endingSlashUrl = to.path + '/'
const endingHtmlUrl = to.path + '.html'
if (isRouteExists(router, endingHtmlUrl)) {
return endingHtmlUrl
} else if (isRouteExists(router, endingSlashUrl)) {
return endingSlashUrl
} else {
return to.path
}
} else if (/\/$/.test(to.path)) {
const endingHtmlUrl = to.path.replace(/\/$/, '') + '.html'
if (isRouteExists(router, endingHtmlUrl)) {
return endingHtmlUrl
} else {
return to.path
}
} else {
return to.path
}
}
}
function isRouteExists(router, path) {
const pathLower = path.toLowerCase()
return router.options.routes.some(route => route.path.toLowerCase() === pathLower)
}
function handlePath(router, to) {
const id = to.query.id
const redirectPath = handleRedirectForCleanUrls(router, to)
if (id) {
return {
path: redirectPath,
hash: '#' + decodeURIComponent(id.toLowerCase())
}
}
if (redirectPath !== to.path) {
return {
path: redirectPath,
hash: decodeURIComponent(to.hash).toLowerCase()
}
}
if (/\bREADME\b/.test(to.path)) {
return {
path: to.path.replace(/\bREADME\b/, ''),
hash: decodeURIComponent(to.hash).toLowerCase()
}
}
}
export default ({
Vue,
options,
router,
siteData
}) => {
let mounted = false
const ScrollBehavior = 'smooth'
router.beforeHooks.unshift((to, from, next) => {
next(handlePath(router, to))
})
router.options.scrollBehavior = function scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return window.scrollTo({
top: savedPosition.y,
behavior: ScrollBehavior,
});
}
else if (to.hash) {
if (Vue.$vuepress.$get('disableScrollBehavior')) {
return false;
}
const selector = decodeURIComponent(to.hash)
return new Promise((resolve, reject) => {
setTimeout(() => {
if (!mounted) mounted = true
const targetElement = document.querySelector(selector);
if (targetElement) {
return window.scrollTo({
top: getElementPosition(targetElement).y,
behavior: ScrollBehavior,
});
}
return resolve(false);
}, mounted ? 0 : 700)
})
}
else {
return window.scrollTo({
top: 0,
behavior: ScrollBehavior,
});
}
}
}
function getElementPosition(el) {
const docEl = document.documentElement;
const docRect = docEl.getBoundingClientRect();
const elRect = el.getBoundingClientRect();
return {
x: elRect.left - docRect.left,
y: elRect.top - docRect.top,
};
}
\ No newline at end of file
<template>
<div class="page-runtime">
<div class="page-snippet">
<slot></slot>
</div>
<div class="code-content">
<iframe class="code-iframe" :src="src" frameborder="0"></iframe>
</div>
</div>
</template>
<script>
export default {
props:{
src:{
type:String,
default:''
}
},
created(){
console.log('this.src', this.src);
}
}
</script>
<style>
.page-runtime {
display: flex;
height: 667px;
}
.page-snippet {
width: 100%;
overflow: hidden;
}
.page-snippet div[class*="language-"]{
width: 100%;
height: 100%;
border-radius: 0;
overflow: hidden;
}
.page-snippet pre[class*="language-"]{
margin: 0;
padding: 10px;
width: 100%;
height: 100%;
overflow: scroll;
box-sizing: border-box;
}
.code-iframe {
flex-shrink: 0;
width: 375px;
height: 667px;
}
</style>
module.exports = {
extend: '@vuepress/theme-default',
plugins: [
['container', {
type: 'preview',
validate: (params) =>{
return params.trim().match(/^preview\s+(.*)$/);
},
render: (tokens, idx,otps,event)=> {
var m = tokens[idx].info.trim().match(/^preview\s+(.*)$/);
if (tokens[idx].nesting === 1) {
// opening tag
return `<CodeSimulator class="code" src="${m && m.length > 0?m[1]:''}">`;
} else {
// closing tag
return `</CodeSimulator>`;
}
}
}],
'@vuepress/back-to-top'
]
}
<template>
<div
class="theme-container"
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
>
<Navbar
v-if="shouldShowNavbar"
@toggle-sidebar="toggleSidebar"
/>
<div
class="sidebar-mask"
@click="toggleSidebar(false)"
/>
<Sidebar
:items="sidebarItems"
@toggle-sidebar="toggleSidebar"
>
<template #top>
<slot name="sidebar-top" />
</template>
<template #bottom>
<slot name="sidebar-bottom" />
</template>
</Sidebar>
<Home v-if="$page.frontmatter.home" />
<Page
v-else
:sidebar-items="sidebarItems"
>
<template #top>
<slot name="page-top" />
</template>
<template #bottom>
<slot name="page-bottom" />
</template>
</Page>
</div>
</template>
<script>
import Home from '@theme/components/Home.vue'
import Navbar from '@theme/components/Navbar.vue'
import Page from '@theme/components/Page.vue'
import Sidebar from '@theme/components/Sidebar.vue'
import { resolveSidebarItems, forbidScroll } from '../util'
import navProvider from '../mixin/navProvider';
export default {
name: 'Layout',
mixins: [ navProvider ],
components: {
Home,
Page,
Sidebar,
Navbar
},
data () {
return {
isSidebarOpen: false
}
},
computed: {
shouldShowNavbar () {
const { themeConfig } = this.$site
const { frontmatter } = this.$page
if (
frontmatter.navbar === false
|| themeConfig.navbar === false) {
return false
}
return (
this.$title
|| themeConfig.logo
|| themeConfig.repo
|| themeConfig.nav
|| this.$themeLocaleConfig.nav
)
},
shouldShowSidebar () {
const { frontmatter } = this.$page
return (
!frontmatter.home
&& frontmatter.sidebar !== false
&& this.sidebarItems.length
)
},
sidebarItems () {
return resolveSidebarItems(
this.$page,
this.$page.regularPath,
this.$site,
this.$localePath
)
},
pageClasses () {
const userPageClass = this.$page.frontmatter.pageClass
return [
{
'no-navbar': !this.shouldShowNavbar,
'sidebar-open': this.isSidebarOpen,
'no-sidebar': !this.shouldShowSidebar
},
userPageClass
]
}
},
mounted () {
this.$router.afterEach(() => {
this.isSidebarOpen = false
})
forbidScroll(this.isSidebarOpen)
this.renderNavLinkState()
},
methods: {
toggleSidebar (to) {
this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
this.$emit('toggle-sidebar', this.isSidebarOpen)
},
// side swipe
onTouchStart (e) {
this.touchStart = {
x: e.changedTouches[0].clientX,
y: e.changedTouches[0].clientY
}
},
onTouchEnd (e) {
const dx = e.changedTouches[0].clientX - this.touchStart.x
const dy = e.changedTouches[0].clientY - this.touchStart.y
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
if (dx > 0 && this.touchStart.x <= 80) {
this.toggleSidebar(true)
} else {
this.toggleSidebar(false)
}
}
},
renderNavLinkState() {
this.$nextTick(() => {
const navs = document.querySelectorAll('nav')
const navLinks = []
navs.forEach(nav => {
nav.querySelectorAll('a').forEach(navLink => {
if(navLink.className.indexOf('external') === -1) {
navLinks.push(navLink)
}
})
})
navLinks.forEach((navLink,index) => {
navLink.classList.remove('router-link-active')
let href = navLink.href.split('/')
href = href[href.length - 2]
const path = (this.$route.fullPath.match(/\/(\w+)+\//) || [])[1]
if (path) {
if (path === href) {
navLink.classList.add('router-link-active')
}
} else {
// 0 => PC
// navLinks.length / 2 => mobile
if( index === 0 || index === navLinks.length / 2) {
navLink.classList.add('router-link-active')
}
}
})
})
}
},
watch: {
isSidebarOpen: forbidScroll,
$route(){
this.renderNavLinkState()
}
}
}
</script>
export default {
inject: ['navConfig', 'customNavBar', 'changeUserNav'],
computed: {
showSubNavBar() {
return !!this.customNavBar[this.navConfig.userNavIndex].items
},
mainNavBarText() {
return this.customNavBar[this.navConfig.userNavIndex].text
},
subNavBarText() {
const curNavBar = this.customNavBar[this.navConfig.userNavIndex]
const curLink = (this.$page.path.match(/\/(\w+)+\/*/) || [])[1]
const item = curNavBar.items ? curNavBar.items.filter(
item => item.type === 'link' && item.link.indexOf(curLink) !== -1
)[0] : curNavBar
return item ? item.text : curNavBar.items[0].text
}
}
}
\ No newline at end of file
import { navbar } from '../../markdown/navbar.config';
export default {
data() {
return { navConfig: { userNavIndex: 0 } }
},
provide() {
return {
navConfig: this.navConfig,
customNavBar: this.customNavBar,
changeUserNav: this.changeUserNav
}
},
created() {
this.customNavBar.forEach((item, index) => {
item.text === this.$page.path.split('/')[1] && (this.navConfig.userNavIndex = index)
})
},
computed: {
customNavBar() {
const list = []
navbar.forEach(item => {
if (item.items && item.items.length) {
list.push(item)
}
item.type === 'link' && list.push(item)
})
return list
},
customNavBarKeys() {
return this.customNavBar.map(item => item.text)
}
},
methods: {
changeUserNav(index) {
this.navConfig.userNavIndex = index
const curNavBar = this.customNavBar[index]
const firstItemLink = curNavBar.items ? curNavBar.items[0].link : curNavBar.link
if (this.$page.path !== firstItemLink) this.$router.push(firstItemLink)
}
},
watch: {
$route(after) {
let navbarIndex = this.customNavBarKeys.indexOf((after.fullPath.match(/\/(\w+)+\/*/) || [])[1])
navbarIndex === -1 && after.fullPath === '/' && (navbarIndex = 0)
this.navConfig.userNavIndex !== navbarIndex && navbarIndex !== -1 && (this.navConfig.userNavIndex = navbarIndex)
}
}
}
\ No newline at end of file
.custom-page-class{
/* 首页几个logo的排版 */
.flex-img-group-view {
display flex
flex-direction row
margin 10px 0
.barcode-view {
display flex
align-items center
flex-direction column
margin 0 5px
margin-bottom 20px
b {
text-align center
}
}
}
.uniapp-home-content {
display flex
flex-wrap wrap
width 100%
justify-content center
.uniapp-home-content-item {
margin-bottom 20px
.uniapp-home-content-item-image {
width 55px
height 55px
flex-shrink 0
img {
height 100%
}
}
p.uniapp-home-content-item-text {
margin-bottom 0px
letter-spacing 0px
color #333
}
.uniapp-home-content-item-title{
font-size 16px
}
}
}
@media screen and (min-width: 768px) {
.flex-img-group-view {
justify-content space-around
}
.uniapp-home-content-item{
width 32%
}
}
@media screen and (max-width: 600px) {
.uniapp-home-content-item{
width 100%
display flex
flex-direction row
}
.uniapp-home-content-item-header {
display flex
flex-direction column
padding-left 15px
}
.uniapp-home-content-item-title{
line-height 10px
}
}
}
img {
image-rendering: -moz-crisp-edges; /* Firefox*/
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /*Webkit (non-standard naming) */
image-rendering: crisp-edges;
-ms-interpolation-mode: nearest-neighbor; /* I (non-standard property) */
}
body.forbid_scroll
height 100%
overflow hidden
{$contentClass}:not(.custom)
> *:first-child
margin-top 0
@media (max-width: $MQMobile)
&
margin-top $navbarHeight
h1, h2, h3, h4, h5, h6
{$contentClass}:not(.custom) > &
margin-top (5rem - $navbarHeight)
padding-top ($navbarHeight - 3rem)
&:first-child
margin-top (3rem - $navbarHeight)
padding-top ($navbarHeight - 3rem)
@media (max-width: $MQMobile)
&
margin-top 3rem
@media (min-width: $MQMobile)
.nav-dropdown
z-index 1
\ No newline at end of file
$navbar-main-navbar-height = $navbarHeight - $navbar-sub-navbar-height
$navbar-logo-height = $navbar-main-navbar-height - 2rem
.navbar
height auto
background-color $navbar-background-color
text-align center
&:not(.navbar-fixed)
position static
.main-navbar-links + .links, .mobile-main-navbar + .links
background-color $navbar-background-color
.home-link
position: absolute
left: $navbar-horizontal-padding
line-height $navbar-logo-height
.title-logo
padding-left 20px
border-left 1px solid #ccc
@media (max-width: 1080px)
&
display none
.sub-navbar
line-height $navbar-sub-navbar-height
border-top-width 1px
.mobile-main-navbar
display none
.mobile-sub-navbar
display none
.main-navbar
color #222
box-shadow 0 1px 0 0 rgba(0,0,0,.06)
position relative
display flex
justify-content center
align-items center
.main-navbar-links
width 50%
white-space: nowrap;
display inline-block
@media (min-width: 1080px) and (max-width: 1680px)
&
flex 1
padding 0 300px
show-after()
opacity 1
transform scaleX(1)
.main-navbar-item
display inline-block
padding 0 3%
position relative
&.active a
color $accentColor
&::after
show-after()
color $accentColor
&>a
&>div>a
color inherit
&:hover
color $accentColor
&::after
content ''
transition: all .2s cubic-bezier(.18,.89,.17,.88),opacity .15s ease
width 32px
height 2px
background-color $accentColor
position absolute
left 50%
margin-left -16px
bottom 0
opacity 0
transform scaleX(0)
@media (max-width: $MQMobile)
$navbar-a-color = #222;
.sidebar
width 100%
.navbar
top 0px !important
height $navbar-main-navbar-height
&
position fixed !important
.main-navbar
justify-content flex-end
.mobile-main-navbar
display inline-block
padding-right 75px
a
color $navbar-a-color
.mobile-links__btn:after
content ""
width 6px
height 4px
background-image url("data:image/svg+xml;charset=UTF-8,%3csvg width='6' height='4' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M5.23575684.6H.76852779L3.0003575 3.09954227 5.23575684.6z' fill='%23000' stroke='%23000' stroke-width='1.2' fill-rule='evenodd'/%3e%3c/svg%3e")
background-repeat no-repeat
background-size contain
display inline-block
vertical-align middle
margin-left 4px
margin-top -2px
position static
border none
transform none
background-color transparent
border-radius 0
.mobile-links__panel
text-align left
display flex
flex-direction column
position fixed
left 0
right 0
top $navbar-main-navbar-height
bottom 0
background-color #f7f7f7
overflow auto
z-index 99
opacity 0
visibility hidden
transition opacity .2s,top .2s
&.open
opacity 1
visibility visible
.main-navbar-item
&.active a
color $accentColor
button.mobile-dropdown-title
a
display block
padding 20px 40px
font-size 17px
position relative
height auto
line-height 1.4
button.mobile-dropdown-title
width 100%
text-align left
a
&::before
content ""
display block
width 12px
height 12px
background-image url("data:image/svg+xml;charset=UTF-8,%3csvg width='12' height='12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M2.99427682 1.3995186L3.88640626.5l4.86067483 4.90093365c.3281374.33085521.331048.86434278 0 1.1981327L3.88640626 11.5l-.89212944-.89951856L7.55696751 6 2.99427682 1.3995186z' fill='%23000' fill-rule='evenodd' fill-opacity='.3'/%3e%3c/svg%3e")
background-size contain
background-repeat no-repeat
position absolute
right 40px
top 50%
margin-top -6px
&::after
content ""
display block
position absolute
bottom 0
left 40px
right 40px
height 1px
background-color rgba(0,0,0,.08)
transform scaleY(.5)
width auto
opacity 1
margin 0
.sub-navbar
.mobile-sub-navbar
display block
background-color white
position relative
&::after
content ""
position absolute
display block
bottom 0
left 0
right 0
height 1px
background-color #e4e8eb
transform scaleY(.5)
.subnavbar__item
a
display block
padding 0 16px
min-width 0
margin 0
background-color transparent
border-radius 0
text-align left
font-size 17px
color $navbar-a-color
height 56px
line-height 56px
font-weight 500
&::after
content ""
display block
width 12px
height 12px
position absolute
right 16px
top 50%
margin-top -6px
background-size contain
background-repeat no-repeat
background-image url("data:image/svg+xml;charset=UTF-8,%3csvg width='12' height='12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M2.99427682 1.3995186L3.88640626.5l4.86067483 4.90093365c.3281374.33085521.331048.86434278 0 1.1981327L3.88640626 11.5l-.89212944-.89951856L7.55696751 6 2.99427682 1.3995186z' fill='%23000' fill-rule='evenodd' fill-opacity='.3'/%3e%3c/svg%3e")
transform rotate(90deg)
emphasize()
position relative
&::before
@media (max-width: $MQMobile)
&
top: 8px;
content: "";
display: block;
width: 4px;
height: 4px;
border-radius: 2px;
background-color: #07c160;
position: absolute;
top: 13px;
left: 18px;
.sidebar>ul.sidebar-links>li>.active + ul>li .sidebar-link.active
&::before
left: 10px;
.sidebar-links ul.sidebar-sub-headers .sidebar-link.active
emphasize()
.sidebar-group.depth-1
.sidebar-links>li>.sidebar-link.active:not(.data-no-emphasize)
emphasize()
\ No newline at end of file
// 布局
$accentColor = #42b983
$contentWidth = 1200px
$navbarHeight = 9rem
$navbar-sub-navbar-height = 5rem
$navbar-background-color = #f7f7f7
\ No newline at end of file
export const hashRE = /#.*$/
export const extRE = /\.(md|html)$/
export const endingSlashRE = /\/$/
export const outboundRE = /^[a-z]+:/i
export function normalize(path) {
return decodeURI(path)
.replace(hashRE, '')
.replace(extRE, '')
}
export function getHash(path) {
const match = path.match(hashRE)
if (match) {
return match[0]
}
}
export function isExternal(path) {
return outboundRE.test(path)
}
export function isMailto(path) {
return /^mailto:/.test(path)
}
export function isTel(path) {
return /^tel:/.test(path)
}
export function ensureExt(path) {
if (isExternal(path)) {
return path
}
const hashMatch = path.match(hashRE)
const hash = hashMatch ? hashMatch[0] : ''
const normalized = normalize(path)
if (endingSlashRE.test(normalized)) {
return path
}
return normalized + '.html' + hash
}
export function isActive(route, path) {
const routeHash = decodeURIComponent(route.hash)
const linkHash = getHash(path)
if (linkHash && routeHash !== linkHash) {
return false
}
const routePath = normalize(route.path)
const pagePath = normalize(path)
return routePath === pagePath
}
export function resolvePage(pages, rawPath, base) {
if (isExternal(rawPath)) {
return {
type: 'external',
path: rawPath
}
}
if (base) {
rawPath = resolvePath(rawPath, base)
}
const path = normalize(rawPath)
const hash = rawPath.split('#')[1]
for (let i = 0; i < pages.length; i++) {
if (normalize(pages[i].regularPath) === path) {
return Object.assign({}, pages[i], {
type: 'page',
path: ensureExt(pages[i].path) + (hash ? `#${hash}` : '')
})
}
}
console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
return {}
}
function resolvePath(relative, base, append) {
const firstChar = relative.charAt(0)
if (firstChar === '/') {
return relative
}
if (firstChar === '?' || firstChar === '#') {
return base + relative
}
const stack = base.split('/')
// remove trailing segment if:
// - not appending
// - appending to trailing slash (last segment is empty)
if (!append || !stack[stack.length - 1]) {
stack.pop()
}
// resolve relative path
const segments = relative.replace(/^\//, '').split('/')
for (let i = 0; i < segments.length; i++) {
const segment = segments[i]
if (segment === '..') {
stack.pop()
} else if (segment !== '.') {
stack.push(segment)
}
}
// ensure leading slash
if (stack[0] !== '') {
stack.unshift('')
}
return stack.join('/')
}
/**
* @param { Page } page
* @param { string } regularPath
* @param { SiteData } site
* @param { string } localePath
* @returns { SidebarGroup }
*/
export function resolveSidebarItems(page, regularPath, site, localePath) {
const { pages, themeConfig } = site
const localeConfig = localePath && themeConfig.locales
? themeConfig.locales[localePath] || themeConfig
: themeConfig
const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
if (pageSidebarConfig === 'auto') {
return resolveHeaders(page)
}
const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
if (!sidebarConfig) {
return []
} else {
const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
if (config === 'auto') {
return resolveHeaders(page)
}
return config
? config.map(item => resolveItem(item, pages, base))
: []
}
}
/**
* @param { Page } page
* @returns { SidebarGroup }
*/
function resolveHeaders(page) {
const headers = groupHeaders(page.headers || [])
return [{
type: 'group',
collapsable: false,
title: page.title,
path: null,
children: headers.map(h => ({
type: 'auto',
title: h.title,
basePath: page.path,
path: page.path + '#' + h.slug,
children: h.children || []
}))
}]
}
export function groupHeaders(headers) {
// group h3s under h2
headers = headers.map(h => Object.assign({}, h))
let lastH2
headers.forEach(h => {
if (h.level === 2) {
lastH2 = h
} else if (lastH2) {
(lastH2.children || (lastH2.children = [])).push(h)
}
})
// TODO h1-h3
return headers.filter(h => h.level === 2)
}
export function resolveNavLinkItem(linkItem) {
return Object.assign(linkItem, {
type: linkItem.items && linkItem.items.length ? 'links' : 'link'
})
}
/**
* @param { Route } route
* @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config
* @returns { base: string, config: SidebarConfig }
*/
export function resolveMatchingConfig(regularPath, config) {
if (Array.isArray(config)) {
return {
base: '/',
config: config
}
}
for (const base in config) {
if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
return {
base,
config: config[base]
}
}
}
return {}
}
function ensureEndingSlash(path) {
return /(\.html|\/)$/.test(path)
? path
: path + '/'
}
function resolveItem(item, pages, base, groupDepth = 1) {
if (typeof item === 'string') {
return resolvePage(pages, item, base)
} else if (Array.isArray(item)) {
return Object.assign(resolvePage(pages, item[0], base), {
title: item[1]
})
} else {
const children = item.children || []
if (children.length === 0 && item.path) {
return Object.assign(resolvePage(pages, item.path, base), {
title: item.title
})
}
return {
type: 'group',
path: item.path,
title: item.title,
sidebarDepth: item.sidebarDepth,
initialOpenGroupIndex: item.initialOpenGroupIndex,
children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)),
collapsable: item.collapsable !== false
}
}
}
export function forbidScroll(use = true) {
if (use) {
const classList = document.body.className.split(' ')
classList.push('forbid_scroll')
document.body.className = classList.join(' ')
} else {
document.body.className = document.body.className.replace(/\s+forbid_scroll/g, '')
}
}
export const os = {
android: false,
ios: false,
mobile: false,
pc: false,
init: function () {
var ua = navigator.userAgent;
if (ua.match(/(Android);?[\s\/]+([\d+.]+)?/)) {
this.android = true;
this.mobile = true;
this.pc = false;
} else if (ua.match(/(iPhone\sOS)\s([\d_]+)/)) {
this.ios = true;
this.mobile = true;
this.pc = false;
} else {
this.android = false;
this.ios = false;
this.mobile = false;
this.pc = true;
}
}
};
\ No newline at end of file
function isExternal(path) {
return /^[a-z]+:/i.test(path)
}
module.exports = {
isExternal
}
\ No newline at end of file
---
pageClass: custom-page-class
---
```uni-app``` 是一个使用 [Vue.js](https://vuejs.org/) 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。
......@@ -6,7 +9,7 @@
`uni-app`在手,做啥都不愁。即使不跨端,```uni-app```也是更好的小程序开发框架([详见](https://ask.dcloud.net.cn/article/35947))、更好的App跨平台框架、更方便的H5开发框架。不管领导安排什么样的项目,你都可以快速交付,不需要转换开发思维、不需要更改开发习惯。
<div class="quick">
<h3 id="快速体验"><a href="/README?id=%e5%bf%ab%e9%80%9f%e4%bd%93%e9%aa%8c" data-id="快速体验" class="anchor"><span>快速体验</span></a></h3>
<h3 id="快速体验"><a href="/#%e5%bf%ab%e9%80%9f%e4%bd%93%e9%aa%8c" data-id="快速体验" class="anchor"><span>快速体验</span></a></h3>
<p>一套代码编到13个平台,这不是梦想。眼见为实,扫描13个二维码,亲自体验最全面的跨平台效果!</p>
<div class="flex-img-group-view">
<a href="//m3w.cn/uniapp" target="_blank" class="clear-style barcode-view">
......
......@@ -4,58 +4,11 @@
* [2. 通过vue-cli命令行](quickstart-cli.md)
* [uni-app的由来](history.md)
* [如何学习](resource.md)
* [框架简介](frame.md)
* vue2教程
* [基础](vue-basics.md)
* [组件](vue-components.md)
* [API](vue-api.md)
* [vuex](vue-vuex.md)
* [从 vue2 迁移到 vue3](migration-to-vue3.md)
* vue3教程
* [基础](vue3-basics.md)
* [组件](vue3-components.md)
* [API](vue3-api.md)
* [vuex](vue3-vuex.md)
* nvue教程
* [综述](nvue-outline.md)
* [样式](nvue-css.md)
* [API](nvue-api.md)
* [事件](nvue-event.md)
* [使用 HTML5+ 注意事项](use-html5plus.md)
* [条件编译 解决各端差异](platform.md)
* [uni-app 跨端开发注意](matter.md)
* [高效开发技巧](snippet.md)
* [性能优化建议](performance.md)
* [宽屏适配指南](adapt.md)
* [开放生态](ecosystem.md)
* [uni_modules插件规范](uni_modules.md)
* [从其他项目转uni-app](translate.md)
* [混合开发](hybrid.md)
* App打包配置
* [图标](app-icons.md)
* [启动界面](app-splashscreen.md)
* [功能模块](app-modules.md)
* [Geolocation(定位)](app-geolocation.md)
* [Payment(支付)](app-payment.md)
* [Apple应用内支付](app-payment-aip.md)
* [支付宝支付](app-payment-alipay.md)
* [微信支付](app-payment-weixin.md)
* [Paypal支付](app-payment-paypal.md)
* [Stripe支付](app-payment-stripe.md)
* [Google支付](app-payment-google.md)
* [Statistic(统计)](app-statistic.md)
* [友盟统计](app-statistic-umeng.md)
* [Google统计](app-statistic-google.md)
* 其它配置
* [iOS符号表文件](app-ios-dsym.md)
* App上架指南
* [国内应用市场上架](android-store.md)
* [未同意隐私政策模式运行](app-disagreemode.md)
* [Google Play上架](android-gp.md)
* [App Store上架](ios-app-store.md)
* App安全问题
* [Android安全漏洞问题解决方案](app-sec-android.md)
* [uni小程序sdk](https://nativesupport.dcloud.net.cn/README)
* [选型指南](select.md)
* [跨端注意](matter.md)
* [常见问题](faq.md)
* [其他项目转uni-app](translate.md)
* [老项目引入uni-app](hybrid.md)
* 运营服务
* [App升级中心](uniCloud/upgrade-center.md)
* [uni一键登录](univerify.md)
......@@ -64,96 +17,6 @@
* [广告变现](uni-ad.md)
* [统一发行页面](m3w.md)
* [案例](case.md)
* [选型评估指南](select.md)
* [常见问题](faq.md)
* 更新日志
* [正式版](release.md)
* [Alpha版](release-note-alpha.md)
<!-- * [更新日志](//update.dcloud.net.cn/hbuilderx/changelog/2.1.1.20190716.html) -->
<!-- <li><a id="update-hock" href="javascript:;" target="__blank">更新日志</a></li> -->
<li class="show-sponsor-in-phone show-last"><a href="//ext.dcloud.net.cn/" target="__blank">插件市场</a></li>
<li class="show-sponsor-in-phone"><a href="//dev.dcloud.net.cn/wish/?channel=uniapp" target="__blank">需求墙</a></li>
<li class="show-sponsor-in-phone"><a href="//dev.dcloud.net.cn/sponsor/?channel=uniapp" target="__blank">赞助我们</a></li>
<div class="contact-box">
<a href="//unicloud.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/7962e8e0-4f2d-11eb-a16f-5b3e54966275.jpg" width="20" height="20"/>
<div class="contact-smg">
<div>uniCloud Web控制台</div>
</div>
</a>
<a href="//ask.dcloud.net.cn/explore/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/73fc4f90-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>论坛</div>
</div>
</a>
<a href="https://uniad.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/765d9820-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>uniAD</div>
</div>
</a>
<a href="https://tongji.dcloud.net.cn/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77159d80-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>uni统计</div>
</div>
</a>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/74cda950-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>
代码仓库:<a href="https://gitee.com/dcloud/uni-app" target="_blank">码云</a><a href="http://github.com/dcloudio/uni-app" target="_blank">GitHub</a>
</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/759713d0-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>官方QQ交流群</div>
<div>群33:498071674 &nbsp;<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=KsL-fqAOIV0-c5Eq_VwRVXRfWuZxSaUP&jump_from=webapi">点此加入</a></div>
<div>群35:713420817(2000人已满)</div>
<div>群34:530305531(2000人已满)</div>
<!-- <div>群33:498071674(2000人已满)</div>-->
<div>群32:166188631(2000人已满)</div>
<div>群31:567471669(2000人已满)</div>
<div>群30:371046920(2000人已满)</div>
<div>群29:202965481(2000人已满)</div>
<div>群28:166188776(2000人已满)</div>
<div>群27:811363410(2000人已满)</div>
<div>群26:147867597(2000人已满)</div>
<div>群25:165297000(2000人已满)</div>
<div>群24:672494800(2000人已满)</div>
<div>群23:599958679(2000人已满)</div>
<div>群22:687186952(2000人已满)</div>
<div>群21:717019120(2000人已满)</div>
<div>群20:165796402(2000人已满)</div>
<div>群19:165657124(2000人已满)</div>
<div>群18:698592271(2000人已满)</div>
<div>群17:951348804(2000人已满)</div>
<div>群16:719211033(2000人已满)</div>
<div>群15:516984120(2000人已满)</div>
<div>群14:465953250(2000人已满)</div>
<div>群13:699478442(2000人已满)</div>
<div>群12:884860657(2000人已满)</div>
<div>群11:296811328(2000人已满)</div>
<div>群10:959059626(2000人已满)</div>
<div>群9:775128777(2000人已满)</div>
<div>群8:695442854(2000人已满)</div>
<div>群7:942061423(2000人已满)</div>
<div>群6:697264024(2000人已满)</div>
<div>群5:731951419(2000人已满)</div>
<div>群4:942702595(2000人已满)</div>
<div>群3:773794803(2000人已满) </div>
<div>群2:901474938(2000人已满) </div>
<div>群1:531031261(2000人已满)</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77df7d30-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>关注微信公众号</div>
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/78a8e7b0-4f2d-11eb-8ff1-d5dcf8779628.jpg" width="90" height="90"/>
</div>
</div>
</div>
* [Alpha版](release-note-alpha.md)
\ No newline at end of file
`uni-app`的js API由标准ECMAScript的js API 和 uni 扩展 API 这两部分组成。
标准ECMAScript的js仅是最基础的js。浏览器基于它扩展了window、document、navigator等对象。小程序也基于标准js扩展了各种wx.xx、my.xx、swan.xx的API。node也扩展了fs等模块。
uni-app基于ECMAScript扩展了uni对象,并且API命名与小程序保持兼容。
## 标准js和浏览器js的区别
`uni-app`的js代码,h5端运行于浏览器中。非h5端(包含小程序和App),Android平台运行在v8引擎中,iOS平台运行在iOS自带的jscore引擎中,都没有运行在浏览器或webview里。
非H5端,虽然不支持window、document、navigator等浏览器的js API,但也支持标准ECMAScript。
请注意不要把浏览器里的js扩展对象等价于标准js。
所以uni-app的非H5端,一样支持标准js,支持if、for等语法,支持字符串、数字、时间、布尔值、数组、自定义对象等变量类型及各种处理方法。仅仅是不支持window、document、navigator等浏览器专用对象。
## 各端特色API调用
除了uni-app框架内置的跨端API,各端自己的特色API也可通过[条件编译](https://uniapp.dcloud.io/platform)自由使用。
......
* [API概述](api/README.md)
* 基础
* [日志打印](api/log.md)
* [定时器](api/timer.md)
* [uni.base64ToArrayBuffer](api/base64ToArrayBuffer?id=base64toarraybuffer)
* [uni.arrayBufferToBase64](api/arrayBufferToBase64?id=arraybuffertobase64)
* [生命周期](api/lifecycle.md)
* [应用级事件](api/application.md)
* [拦截器](api/interceptor.md)
* [全局API](api/global.md)
* 网络
* [发起请求](api/request/request.md)
* [上传、下载](api/request/network-file.md)
* [WebSocket](api/request/websocket.md)
* [SocketTask](api/request/socket-task.md)
* [mDNS](api/request/mDNS.md)
* [UDP 通信](api/request/UDP.md)
* 路由与页面跳转
* [uni.navigateTo](/api/router?id=navigateto)
* [uni.redirectTo](/api/router?id=redirectto)
* [uni.reLaunch](/api/router?id=relaunch)
* [uni.switchTab](/api/router?id=switchtab)
* [uni.navigateBack](/api/router?id=navigateback)
* [uni.preloadPage](/api/preload-page)
* [窗口动画](/api/router?id=animation)
* 数据缓存
* [uni.setStorage](/api/storage/storage?id=setstorage)
* [uni.setStorageSync](/api/storage/storage?id=setStorageSync)
* [uni.getStorage](/api/storage/storage?id=getStorage)
* [uni.getStorageSync](/api/storage/storage?id=getStorageSync)
* [uni.getStorageInfo](/api/storage/storage?id=getStorageInfo)
* [uni.getStorageInfoSync](/api/storage/storage?id=getStorageInfoSync)
* [uni.removeStorage](/api/storage/storage?id=removeStorage)
* [uni.removeStorageSync](/api/storage/storage?id=removeStorageSync)
* [uni.clearStorage](/api/storage/storage?id=clearStorage)
* [uni.clearStorageSync](/api/storage/storage?id=clearstoragesync)
* 位置
* [获取位置](api/location/location.md)
* [查看位置](api/location/open-location.md)
* [地图组件控制](api/location/map.md)
* 媒体
* [图片](api/media/image.md)
* [文件](api/media/file.md)
* [录音管理](api/media/record-manager.md)
* [背景音频播放管理](api/media/background-audio-manager.md)
* [音频组件控制](api/media/audio-context.md)
* [视频](api/media/video.md)
* [视频组件控制](api/media/video-context.md)
* [相机组件控制](api/media/camera-context.md)
* [直播组件控制](api/media/live-player-context.md)
* [富文本](api/media/editor-context.md)
* [音视频合成](api/media/media-container.md)
* 设备
* [系统信息](api/system/info.md)
* [内存](api/system/memory.md)
* [网络状态](api/system/network.md)
* [系统主题](api/system/theme.md)
* [加速度计](api/system/accelerometer.md)
* [罗盘](api/system/compass.md)
* [陀螺仪](api/system/gyroscope.md)
* [拨打电话](api/system/phone.md)
* [扫码](api/system/barcode.md)
* [剪贴板](api/system/clipboard.md)
* [屏幕](api/system/brightness.md)
* [用户截屏事件](api/system/capture-screen.md)
* [振动](api/system/vibrate.md)
* [手机联系人](api/system/contact.md)
* [蓝牙](api/system/bluetooth.md)
* [低功耗蓝牙](api/system/ble.md)
* [iBeacon](api/system/ibeacon.md)
* [Wi-Fi](api/system/wifi.md)
* [电量](api/system/batteryInfo.md)
* [NFC](api/system/nfc.md)
* [设备方向](api/system/deviceMotion.md)
* [生物认证](api/system/authentication.md)
* [Worker](api/worker.md)
* 键盘
* [uni.hideKeyboard](/api/key?id=hidekeyboard)
* [uni.onKeyboardHeightChange](/api/key?id=onkeyboardheightchange)
* [uni.offKeyboardHeightChange](/api/key?id=offkeyboardheightchange)
* 界面
* [交互反馈](api/ui/prompt.md)
* [设置导航条](api/ui/navigationbar.md)
* [设置TabBar](api/ui/tabbar.md)
* [背景](api/ui/bgcolor.md)
* [动画](api/ui/animation?id=unicreateanimationobject)
* [滚动](api/ui/scroll)
* [窗口](api/ui/window.md)
* [宽屏适配](api/ui/adapt.md)
* [字体](api/ui/font.md)
* [下拉刷新](api/ui/pulldown.md)
* [节点信息](api/ui/nodes-info.md)
* [节点布局相交状态](api/ui/intersection-observer.md)
* [媒体查询](api/ui/media-query-observer.md)
* [自定义组件](api/ui/nextTick.md)
* [菜单](api/ui/menuButton.md)
* [语言](api/ui/locale.md)
* 页面和窗体
* [页面](api/window/window.md)
* [页面通讯](api/window/communication.md)
* [subNVue原生子窗体](api/window/subNVues.md)
* 文件
* [uni.saveFile](/api/file/file?id=savefile)
* [uni.getSavedFileList](/api/file/file?id=getSavedFileList)
* [uni.getSavedFileInfo](/api/file/file?id=getSavedFileInfo)
* [uni.removeSavedFile](/api/file/file?id=removeSavedFile)
* [uni.getFileInfo](/api/file/file?id=getFileInfo)
* [uni.openDocument](/api/file/file?id=openDocument)
* [uni.getFileSystemManager](/api/file/getFileSystemManager)
* 绘画
* [uni.createOffscreenCanvas](api/canvas/createOffscreenCanvas.md)
* [uni.createCanvasContext](api/canvas/createCanvasContext.md)
* [uni.canvasToTempFilePath](api/canvas/canvasToTempFilePath.md)
* [uni.canvasPutImageData](api/canvas/canvasPutImageData.md)
* [uni.canvasGetImageData](api/canvas/canvasGetImageData.md)
* [CanvasContext](api/canvas/CanvasContext.md)
* [CanvasGradient](api/canvas/CanvasGradient.md)
* 广告
* [激励视频广告](api/a-d/rewarded-video.md)
* [全屏视频广告](api/a-d/full-screen-video.md)
* [内容联盟广告](api/a-d/content-page.md)
* [插屏广告](api/a-d/interstitial.md)
* [互动游戏](api/a-d/interactive.md)
* 第三方服务
* [获取服务供应商](api/plugins/provider.md)
* [登录](api/plugins/login.md)
* [分享](api/plugins/share.md)
* [支付](api/plugins/payment.md)
* [推送](api/plugins/push.md)
* [语音](api/plugins/voice.md)
* [一键生成iOS通用链接](api/plugins/universal-links.md)
* [uniCloud](api/uniCloud.md)
* 平台扩展
* [App原生插件](api/extend/native-plugin.md)
* 其他
* [授权](api/other/authorize.md)
* [设置](api/other/setting.md)
* [收货地址](api/other/choose-address.md)
* [获取发票抬头](api/other/invoice-title.md)
* [小程序跳转](api/other/open-miniprogram.md)
* [账号信息](api/other/getAccountInfoSync.md)
* [运动(计步器)](api/other/sport.md)
* [统计](api/other/report.md)
* [卡券](api/other/card.md)
* [模板消息](api/other/template.md)
* [订阅消息](api/other/requestSubscribeMessage.md)
* [小程序更新](api/other/update.md)
* [调试](api/other/set-enable-debug.md)
* [获取第三方平台数据](api/other/get-extconfig.md)
<li></li>
<div class="contact-box">
<a href="//unicloud.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/7962e8e0-4f2d-11eb-a16f-5b3e54966275.jpg" width="20" height="20"/>
<div class="contact-smg">
<div>uniCloud Web控制台</div>
</div>
</a>
<a href="//ask.dcloud.net.cn/explore/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/73fc4f90-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>论坛</div>
</div>
</a>
<a href="https://uniad.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/765d9820-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>uniAD</div>
</div>
</a>
<a href="https://tongji.dcloud.net.cn/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77159d80-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>uni统计</div>
</div>
</a>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/74cda950-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>
代码仓库:<a href="https://gitee.com/dcloud/uni-app" target="_blank">码云</a><a href="http://github.com/dcloudio/uni-app" target="_blank">GitHub</a>
</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/759713d0-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>官方QQ交流群</div>
<div>群10:959059626 &nbsp;<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=v52yQvGY3G0t1sg9Xm3ulLgONkDNfoYZ&jump_from=webapi">点此加入</a></div>
<div>群35:713420817(2000人已满)</div>
<div>群34:530305531(2000人已满)</div>
<div>群33:498071674(2000人已满)</div>
<div>群32:166188631(2000人已满)</div>
<div>群31:567471669(2000人已满)</div>
<div>群30:371046920(2000人已满)</div>
<div>群29:202965481(2000人已满)</div>
<div>群28:166188776(2000人已满)</div>
<div>群27:811363410(2000人已满)</div>
<div>群26:147867597(2000人已满)</div>
<div>群25:165297000(2000人已满)</div>
<div>群24:672494800(2000人已满)</div>
<div>群23:599958679(2000人已满)</div>
<div>群22:687186952(2000人已满)</div>
<div>群21:717019120(2000人已满)</div>
<div>群20:165796402(2000人已满)</div>
<div>群19:165657124(2000人已满)</div>
<div>群18:698592271(2000人已满)</div>
<div>群17:951348804(2000人已满)</div>
<div>群16:719211033(2000人已满)</div>
<div>群15:516984120(2000人已满)</div>
<div>群14:465953250(2000人已满)</div>
<div>群13:699478442(2000人已满)</div>
<div>群12:884860657(2000人已满)</div>
<div>群11:296811328(2000人已满)</div>
<!-- <div>群10:959059626(2000人已满)</div> -->
<div>群9:775128777(2000人已满)</div>
<div>群8:695442854(2000人已满)</div>
<div>群7:942061423(2000人已满)</div>
<div>群6:697264024(2000人已满)</div>
<div>群5:731951419(2000人已满)</div>
<div>群4:942702595(2000人已满)</div>
<div>群3:773794803(2000人已满) </div>
<div>群2:901474938(2000人已满) </div>
<div>群1:531031261(2000人已满)</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77df7d30-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>关注微信公众号</div>
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/78a8e7b0-4f2d-11eb-8ff1-d5dcf8779628.jpg" width="90" height="90"/>
</div>
</div>
</div>
* [API概述](api/README.md)
* [概述](api/README.md)
* 基础
* [日志打印](api/log.md)
* [定时器](api/timer.md)
......@@ -130,8 +130,6 @@
* [语音](api/plugins/voice.md)
* [一键生成iOS通用链接](api/plugins/universal-links.md)
* [uniCloud](api/uniCloud.md)
* 平台扩展
* [App原生插件](api/extend/native-plugin.md)
* 其他
* [授权](api/other/authorize.md)
* [设置](api/other/setting.md)
......@@ -146,88 +144,4 @@
* [订阅消息](api/other/requestSubscribeMessage.md)
* [小程序更新](api/other/update.md)
* [调试](api/other/set-enable-debug.md)
* [获取第三方平台数据](api/other/get-extconfig.md)
<li></li>
<div class="contact-box">
<a href="//unicloud.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/7962e8e0-4f2d-11eb-a16f-5b3e54966275.jpg" width="20" height="20"/>
<div class="contact-smg">
<div>uniCloud Web控制台</div>
</div>
</a>
<a href="//ask.dcloud.net.cn/explore/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/73fc4f90-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>论坛</div>
</div>
</a>
<a href="https://uniad.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/765d9820-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>uniAD</div>
</div>
</a>
<a href="https://tongji.dcloud.net.cn/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77159d80-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>uni统计</div>
</div>
</a>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/74cda950-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>
代码仓库:<a href="https://gitee.com/dcloud/uni-app" target="_blank">码云</a><a href="http://github.com/dcloudio/uni-app" target="_blank">GitHub</a>
</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/759713d0-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>官方QQ交流群</div>
<div>群10:959059626 &nbsp;<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=v52yQvGY3G0t1sg9Xm3ulLgONkDNfoYZ&jump_from=webapi">点此加入</a></div>
<div>群35:713420817(2000人已满)</div>
<div>群34:530305531(2000人已满)</div>
<div>群33:498071674(2000人已满)</div>
<div>群32:166188631(2000人已满)</div>
<div>群31:567471669(2000人已满)</div>
<div>群30:371046920(2000人已满)</div>
<div>群29:202965481(2000人已满)</div>
<div>群28:166188776(2000人已满)</div>
<div>群27:811363410(2000人已满)</div>
<div>群26:147867597(2000人已满)</div>
<div>群25:165297000(2000人已满)</div>
<div>群24:672494800(2000人已满)</div>
<div>群23:599958679(2000人已满)</div>
<div>群22:687186952(2000人已满)</div>
<div>群21:717019120(2000人已满)</div>
<div>群20:165796402(2000人已满)</div>
<div>群19:165657124(2000人已满)</div>
<div>群18:698592271(2000人已满)</div>
<div>群17:951348804(2000人已满)</div>
<div>群16:719211033(2000人已满)</div>
<div>群15:516984120(2000人已满)</div>
<div>群14:465953250(2000人已满)</div>
<div>群13:699478442(2000人已满)</div>
<div>群12:884860657(2000人已满)</div>
<div>群11:296811328(2000人已满)</div>
<!-- <div>群10:959059626(2000人已满)</div> -->
<div>群9:775128777(2000人已满)</div>
<div>群8:695442854(2000人已满)</div>
<div>群7:942061423(2000人已满)</div>
<div>群6:697264024(2000人已满)</div>
<div>群5:731951419(2000人已满)</div>
<div>群4:942702595(2000人已满)</div>
<div>群3:773794803(2000人已满) </div>
<div>群2:901474938(2000人已满) </div>
<div>群1:531031261(2000人已满)</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77df7d30-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>关注微信公众号</div>
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/78a8e7b0-4f2d-11eb-8ff1-d5dcf8779628.jpg" width="90" height="90"/>
</div>
</div>
</div>
* [获取第三方平台数据](api/other/get-extconfig.md)
\ No newline at end of file
......@@ -9,7 +9,7 @@
内容联盟广告是一个原生全屏组件,大小不可控制
如果需要嵌入到页面控制大小请使用 [短视频内容联盟组件<ad-content-page>](https://uniapp.dcloud.net.cn/component/ad-content-page)
如果需要嵌入到页面控制大小请使用 [短视频内容联盟组件<ad-content-page />](https://uniapp.dcloud.net.cn/component/ad-content-page)
**平台差异说明**
......
......@@ -43,7 +43,7 @@ export default {
}
```
```
```js
// 在起始页面跳转到test.vue页面,并监听test.vue发送过来的事件数据
uni.navigateTo({
url: 'pages/test?id=1',
......
......@@ -3,32 +3,46 @@
这个文件的作用包括:调用应用生命周期函数、配置全局样式、配置全局的存储globalData
应用生命周期仅可在`App.vue`中监听,在页面监听无效。
### 应用生命周期
## 应用生命周期
``uni-app`` 支持 onLaunch、onShow、onHide 等应用生命周期函数,详情请参考[应用生命周期](/collocation/frame/lifecycle?id=应用生命周期)
``uni-app`` 支持如下应用生命周期函数:
|函数名|说明|
|:-|:-|
|onLaunch|当``uni-app`` 初始化完成时触发(全局只触发一次)|
|onShow|当 ``uni-app`` 启动,或从后台进入前台显示|
|onHide|当 ``uni-app`` 从前台进入后台|
|onError|当 ``uni-app`` 报错时触发|
|onUniNViewMessage|对 ``nvue`` 页面发送的数据进行监听,可参考 [nvue 向 vue 通讯](https://uniapp.dcloud.io/tutorial/nvue-api?id=communication)|
|onUnhandledRejection|对未处理的 Promise 拒绝事件监听函数(2.8.1+)|
|onPageNotFound|页面不存在监听函数|
|onThemeChange|监听系统主题变化|
**示例代码**
```html
<script>
export default {
onLaunch: function() {
console.log('App Launch,app启动')
},
onShow: function() {
console.log('App Show,app展现在前台')
},
onHide: function() {
console.log('App Hide,app不再展现在前台')
}
}
</script>
<script>
// 只能在App.vue里监听应用的生命周期
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
```
**注意**
- **应用生命周期仅可在`App.vue`中监听,在其它页面监听无效**
- onlaunch里进行页面跳转,如遇白屏报错,请参考[https://ask.dcloud.net.cn/article/35942](https://ask.dcloud.net.cn/article/35942)
- `App.vue` 不能写模板
- onPageNotFound 页面实际上已经打开了(比如通过分享卡片、小程序码)且发现页面不存在,才会触发,api 跳转不存在的页面不会触发(如 uni.navigateTo)
### globalData
## globalData
小程序有globalData,这是一种简单的全局变量机制。这套机制在uni-app里也可以使用,并且全端通用。
**以下是 App.vue 中定义globalData的相关配置:**
......@@ -54,7 +68,7 @@ nvue的weex编译模式中使用globalData的话,由于weex生命周期不支
globalData是简单的全局变量,如果使用状态管理,请使用`vuex`(main.js中定义)
### 全局样式
## 全局样式
`App.vue`中,可以定义一些全局通用样式,例如需要加一个通用的背景色,首屏页面渲染的动画等都可以写在App.vue中。
注意如果工程下同时有vue和nvue文件,全局样式的所有css会应用于所有文件,而nvue支持的css有限,编译器会在控制台报警,提示某些css无法在nvue中支持。此时需要把nvue不支持的css写在单独的条件编译里。如:
......
* 配置
* [pages.json 页面路由](collocation/pages.md)
* [manifest.json 应用配置](collocation/manifest.md)
* [package.json](collocation/package.md)
* [vue.config.js](collocation/vue-config.md)
* [uni.scss](collocation/uni-scss.md)
* [App.vue](collocation/App.md)
* [main.js](collocation/main.md)
* [env](collocation/env.md)
* [plugin.json 生成小程序插件](collocation/miniprogram-plugin.md)
* 框架接口
* [日志打印](collocation/frame/log.md)
* [定时器](collocation/frame/timer.md)
* [生命周期](collocation/frame/lifecycle.md)
* [页面](collocation/frame/window.md)
* [页面通讯](collocation/frame/communication.md)
* [SSR服务端渲染](collocation/ssr.md)
* [国际化](collocation/i18n.md)
* 自动化测试
* [快速开始](collocation/auto/quick-start.md)
* [API](collocation/auto/api.md)
* [HBuilderX自动化测试插件](collocation/auto/hbuilderx-extension/index.md)
* [CLI项目自动化测试](collocation/auto/uniapp-cli-project.md)
\ No newline at end of file
* 配置
* [pages.json 页面路由](collocation/pages.md)
* [manifest.json 应用配置](collocation/manifest.md)
* [package.json](collocation/package.md)
* [vue.config.js](collocation/vue-config.md)
* [uni.scss](collocation/uni-scss.md)
* [App.vue](collocation/App.md)
* [main.js](collocation/main.md)
* [env](collocation/env.md)
* [plugin.json 生成小程序插件](collocation/miniprogram-plugin.md)
* 框架接口
* [日志打印](collocation/frame/log.md)
* [定时器](collocation/frame/timer.md)
* [生命周期](collocation/frame/lifecycle.md)
* [页面](collocation/frame/window.md)
* [页面通讯](collocation/frame/communication.md)
* [SSR服务端渲染](collocation/ssr.md)
* [国际化](collocation/i18n.md)
* 自动化测试
* [快速开始](collocation/auto/quick-start.md)
* [API](collocation/auto/api.md)
* [HBuilderX自动化测试插件](collocation/auto/hbuilderx-extension/index.md)
* [CLI项目自动化测试](collocation/auto/uniapp-cli-project.md)
<li></li>
<div class="contact-box">
<a href="//unicloud.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/7962e8e0-4f2d-11eb-a16f-5b3e54966275.jpg" width="20" height="20"/>
<div class="contact-smg">
<div>uniCloud Web控制台</div>
</div>
</a>
<a href="//ask.dcloud.net.cn/explore/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/73fc4f90-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>论坛</div>
</div>
</a>
<a href="https://uniad.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/765d9820-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>uniAD</div>
</div>
</a>
<a href="https://tongji.dcloud.net.cn/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77159d80-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>uni统计</div>
</div>
</a>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/74cda950-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>
代码仓库:<a href="https://gitee.com/dcloud/uni-app" target="_blank">码云</a><a href="http://github.com/dcloudio/uni-app" target="_blank">GitHub</a>
</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/759713d0-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>官方QQ交流群</div>
<div>群14:465953250 &nbsp;<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=mt5fF6KNaOZThiQoWEiG9vxnTWmNMyeZ&jump_from=webapi">点此加入</a></div>
<div>群35:713420817(2000人已满)</div>
<div>群34:530305531(2000人已满)</div>
<div>群33:498071674(2000人已满)</div>
<div>群32:166188631(2000人已满)</div>
<div>群31:567471669(2000人已满)</div>
<div>群30:371046920(2000人已满)</div>
<div>群29:202965481(2000人已满)</div>
<div>群28:166188776(2000人已满)</div>
<div>群27:811363410(2000人已满)</div>
<div>群26:147867597(2000人已满)</div>
<div>群25:165297000(2000人已满)</div>
<div>群24:672494800(2000人已满)</div>
<div>群23:599958679(2000人已满)</div>
<div>群22:687186952(2000人已满)</div>
<div>群21:717019120(2000人已满)</div>
<div>群20:165796402(2000人已满)</div>
<div>群19:165657124(2000人已满)</div>
<div>群18:698592271(2000人已满)</div>
<div>群17:951348804(2000人已满)</div>
<div>群16:719211033(2000人已满)</div>
<div>群15:516984120(2000人已满)</div>
<!-- <div>群14:465953250(2000人已满)</div> -->
<div>群13:699478442(2000人已满)</div>
<div>群12:884860657(2000人已满)</div>
<div>群11:296811328(2000人已满)</div>
<div>群10:959059626(2000人已满)</div>
<div>群9:775128777(2000人已满)</div>
<div>群8:695442854(2000人已满)</div>
<div>群7:942061423(2000人已满)</div>
<div>群6:697264024(2000人已满)</div>
<div>群5:731951419(2000人已满)</div>
<div>群4:942702595(2000人已满)</div>
<div>群3:773794803(2000人已满) </div>
<div>群2:901474938(2000人已满) </div>
<div>群1:531031261(2000人已满)</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77df7d30-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>关注微信公众号</div>
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/78a8e7b0-4f2d-11eb-8ff1-d5dcf8779628.jpg" width="90" height="90"/>
</div>
</div>
</div>
* [pages.json 页面路由](collocation/pages.md)
* [manifest.json 应用配置](collocation/manifest.md)
* [package.json](collocation/package.md)
* [vue.config.js](collocation/vue-config.md)
* [uni.scss](collocation/uni-scss.md)
* [App.vue](collocation/App.md)
* [main.js](collocation/main.md)
* [plugin.json 生成小程序插件](collocation/miniprogram-plugin.md)
\ No newline at end of file
> 自 HBuilderX 2.0.0 起支持,[使用指南](https://ask.dcloud.net.cn/article/36010)
### uni.$emit(eventName,OBJECT)
触发全局的自定事件。附加参数都会传给监听器回调。
|属性 |类型 |描述 |
|--- |--- |--- |
|eventName |String |事件名 |
|OBJECT |Object |触发事件携带的附加参数 |
**代码示例**
```javascript
uni.$emit('update',{msg:'页面更新'})
```
### uni.$on(eventName,callback)
监听全局的自定义事件。事件可以由 uni.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数。
|属性 |类型 |描述 |
|--- |--- |--- |
|eventName |String |事件名 |
|callback |Function |事件的回调函数 |
**代码示例**
```javascript
uni.$on('update',function(data){
console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
})
```
### uni.$once(eventName,callback)
监听全局的自定义事件。事件可以由 uni.$emit 触发,但是只触发一次,在第一次触发之后移除监听器。
|属性 |类型 |描述 |
|--- |--- |--- |
|eventName |String |事件名 |
|callback |Function |事件的回调函数 |
**代码示例**
```javascript
uni.$once('update',function(data){
console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
})
```
### uni.$off([eventName, callback])
移除全局自定义事件监听器。
|属性 |类型 |描述 |
|--- |--- |--- |
|eventName |Array<String> |事件名 |
|callback |Function |事件的回调函数 |
**Tips**
- 如果没有提供参数,则移除所有的事件监听器;
- 如果只提供了事件,则移除该事件所有的监听器;
- 如果同时提供了事件与回调,则只移除这个回调的监听器;
- 提供的回调必须跟$on的回调为同一个才能移除这个回调的监听器;
**代码示例**
`$emit``$on``$off`常用于跨页面、跨组件通讯,这里为了方便演示放在同一个页面
```html
<template>
<view class="content">
<view class="data">
<text>{{val}}</text>
</view>
<button type="primary" @click="comunicationOff">结束监听</button>
</view>
</template>
<script>
export default {
data() {
return {
val: 0
}
},
onLoad() {
setInterval(()=>{
uni.$emit('add', {
data: 2
})
},1000)
uni.$on('add', this.add)
},
methods: {
comunicationOff() {
uni.$off('add', this.add)
},
add(e) {
this.val += e.data
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.data {
text-align: center;
line-height: 40px;
margin-top: 40px;
}
button {
width: 200px;
margin: 20px 0;
}
</style>
```
**注意事项**
- uni.$emit、 uni.$on 、 uni.$once 、uni.$off 触发的事件都是 App 全局级别的,跨任意组件,页面,nvue,vue 等
- 使用时,注意及时销毁事件监听,比如,页面 onLoad 里边 uni.$on 注册监听,onUnload 里边 uni.$off 移除,或者一次性的事件,直接使用 uni.$once 监听
## console
向控制台打印日志信息。
### debug
向控制台打印 debug 日志
注:App 端 debug 方法等同于 log 方法。
### log
向控制台打印 log 日志
### info
向控制台打印 info 日志
### warn
向控制台打印 warn 日志
### error
向控制台打印 error 日志
注意:
- 不同平台对于 console 方法的支持存在差异,建议在开发过程中只使用文档中提到的方法。
- HBuilderX中有2个重要的代码块,敲`clog`:可直接输出`console.log()`;敲`clogv`:可输出`console.log(": " + );`,并且出现双光标,方便把变量名称和值同时打印出来。
## setTimeout(callback, delay, rest)
设定一个定时器。在定时到期以后执行注册的回调函数
**参数说明**
|参数|类型|必填|说明|
|:-|:-|:-|:-|
|callback|Function|是|回调函数|
|delay|Number|否|延迟的时间,函数的调用会在该延迟之后发生,单位 ms|
|rest|Any|否|param1, param2, ..., paramN 等附加参数,它们会作为参数传递给回调函数|
**返回值**
|返回值|类型|说明|
|:-|:-|:-|
|timeoutID|Number|定时器的编号,这个值可以传递给 [clearTimeout](/api/timer?id=cleartimeout) 来取消该定时|
## clearTimeout(timeoutID)
取消由 setTimeout 设置的定时器。
**参数说明**
|参数|类型|必填|说明|
|:-|:-|:-|:-|
|timeoutID|Number|是|要取消的定时器的 ID|
## setInterval(callback, delay, rest)
设定一个定时器。按照指定的周期(以毫秒计)来执行注册的回调函数
**参数说明**
|参数|类型|必填|说明|
|:-|:-|:-|:-|
|callback|Function|是|回调函数|
|delay|Number|否|延迟的时间,函数的调用会在该延迟之后发生,单位 ms|
|rest|Any|否|param1, param2, ..., paramN 等附加参数,它们会作为参数传递给回调函数|
**返回值**
|返回值|类型|说明|
|:-|:-|:-|
|intervalID|Number|定时器的编号,这个值可以传递给 [clearInterval](/api/timer?id=clearinterval) 来取消该定时|
## clearInterval(intervalID)
取消由 setInterval 设置的定时器。
**参数说明**
|参数|类型|必填|说明|
|:-|:-|:-|:-|
|intervalID|Number|是|要取消的定时器的 ID|
## 注意事项
* App 端返回的定时器编号可能为 String 类型,使用时无需主动转换为 Number 类型
\ No newline at end of file
### getApp()
```getApp()``` 函数用于获取当前应用实例,一般用于获取globalData 。
**实例**
```javascript
const app = getApp()
console.log(app.globalData)
```
**注意:**
- 不要在定义于 `App()` 内的函数中,或调用 `App` 前调用 `getApp()` ,可以通过 `this.$scope` 获取对应的app实例
- 通过 `getApp()` 获取实例之后,不要私自调用生命周期函数。
- 当在首页`nvue`中使用`getApp()`不一定可以获取真正的`App`对象。对此提供了`const app = getApp({allowDefault: true})`用来获取原始的`App`对象,可以用来在首页对`globalData`等初始化
### getCurrentPages()
```getCurrentPages()``` 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。
**注意:** ``getCurrentPages()``仅用于展示页面栈的情况,请勿修改页面栈,以免造成页面状态错误。
每个页面实例的方法属性列表:
|方法|描述|平台说明|
|---|---|---|
|page.$getAppWebview()|获取当前页面的webview对象实例|App|
|page.route|获取当前页面的路由|&nbsp;|
Tips:
* ``navigateTo``, ``redirectTo`` 只能打开非 tabBar 页面。
* ``switchTab`` 只能打开 ``tabBar`` 页面。
* ``reLaunch`` 可以打开任意页面。
* 页面底部的 ``tabBar`` 由页面决定,即只要是定义为 ``tabBar`` 的页面,底部都有 ``tabBar``。
* 不能在 ```App.vue``` 里面进行页面跳转。
### $getAppWebview()
```uni-app``` 在 ```getCurrentPages()```获得的页面里内置了一个方法 ```$getAppWebview()``` 可以得到当前webview的对象实例,从而实现对 webview 更强大的控制。在 html5Plus 中,plus.webview具有强大的控制能力,可参考:[WebviewObject](http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject)。
但`uni-app`框架有自己的窗口管理机制,请不要自己创建和销毁webview,如有需求覆盖子窗体上去,请使用[原生子窗体subNvue](/api/window/subNVues)。
**注意:此方法仅 App 支持**
**示例:**
获取当前页面 webview 的对象实例
```javascript
export default {
data() {
return {
title: 'Hello'
}
},
onLoad() {
// #ifdef APP-PLUS
const currentWebview = this.$scope.$getAppWebview(); //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
currentWebview.setBounce({position:{top:'100px'},changeoffset:{top:'0px'}}); //动态重设bounce效果
// #endif
}
}
```
获取指定页面 webview 的对象实例
`getCurrentPages()`可以得到所有页面对象,然后根据数组,可以取指定的页面webview对象
```javascript
var pages = getCurrentPages();
var page = pages[pages.length - 1];
// #ifdef APP-PLUS
var currentWebview = page.$getAppWebview();
console.log(currentWebview.id);//获得当前webview的id
console.log(currentWebview.isVisible());//查询当前webview是否可见
);
// #endif
```
uni-app自带的web-view组件,是页面中新插入的一个子webview。获取该对象的方法见:[https://ask.dcloud.net.cn/article/35036](https://ask.dcloud.net.cn/article/35036)
\ No newline at end of file
`main.js`是uni-app的入口文件,主要作用是初始化`vue`实例、定义全局组件、使用需要的插件如vuex。
首先引入了`Vue`库和`App.vue`,创建了一个`vue`实例,并且挂载`vue`实例。
```
```js
import Vue from 'vue'
import App from './App'
import pageHead from './components/page-head.vue' //全局引用page-head组件
......
......@@ -187,13 +187,13 @@ splash(启动封面)是App必然存在的、不可取消的。
|属性|类型|说明|
|:-|:-|:-|
|title|String|页面标题,默认使用 manifest.json 的 name|
|template|String|index.html模板路径,相对于应用根目录,可定制生成的 html 代码。参考:[自定义模板](collocation/manifest?id=h5-template)|
|router|Object|参考:[router](collocation/manifest?id=h5-router)|
|async|Object|参考:[async](collocation/manifest?id=h5-async)|
|devServer|Object|开发环境 server 配置,参考:[devServer](collocation/manifest?id=devserver)|
|publicPath|String|引用资源的地址前缀,仅发布时生效。参考:[publicPath](collocation/manifest?id=publicPath)|
|sdkConfigs|String|SDK配置,例如地图... 参考:[sdkConfigs](collocation/manifest?id=h5sdkconfig)|
|optimization|Object|打包优化配置(HBuilderX 2.1.5 以上支持),参考[optimization](collocation/manifest?id=optimization)|
|template|String|index.html模板路径,相对于应用根目录,可定制生成的 html 代码。参考:[自定义模板](/collocation/manifest?id=h5-template)|
|router|Object|参考:[router](/collocation/manifest?id=h5-router)|
|async|Object|参考:[async](/collocation/manifest?id=h5-async)|
|devServer|Object|开发环境 server 配置,参考:[devServer](/collocation/manifest?id=devserver)|
|publicPath|String|引用资源的地址前缀,仅发布时生效。参考:[publicPath](/collocation/manifest?id=publicPath)|
|sdkConfigs|String|SDK配置,例如地图... 参考:[sdkConfigs](/collocation/manifest?id=h5sdkconfig)|
|optimization|Object|打包优化配置(HBuilderX 2.1.5 以上支持),参考[optimization](/collocation/manifest?id=optimization)|
|uniStatistics|Object|[H5 是否开启 uni 统计,配置方法同全局配置](/collocation/manifest?id=uniStatistics)||
#### 自定义模板@h5-template
......@@ -332,7 +332,7 @@ Tips:`uni-app` 中 `manifest.json->h5->devServer` 实际上对应 `webpack`
|:-|:-|:-|:-|
|prefetch|Boolean|false|资源预取|
|preload|Boolean|false|资源预加载|
|treeShaking|Object||摇树优化,根据项目需求,动态打包框架所需的组件及API,保持框架代码最精简化,参考[treeShaking](collocation/manifest?id=treeshaking)|
|treeShaking|Object||摇树优化,根据项目需求,动态打包框架所需的组件及API,保持框架代码最精简化,参考[treeShaking](/collocation/manifest?id=treeshaking)|
##### treeShaking
......@@ -530,7 +530,7 @@ Tips:关于摇树优化(treeShaking)原理及优化结果,参考:[http
**分包内静态文件示例**
```
```json
"subPackages": [{
"root": "pages/sub",
"pages": [{
......@@ -553,7 +553,7 @@ Tips:关于摇树优化(treeShaking)原理及优化结果,参考:[http
**manifest.json配置**
```
```json
"quickapp-webview": {// 快应用通用配置
"icon": "/static/logo.png",
"package": "com.example.demo",
......
> 本文档意在介绍如何把uni-app项目编译为小程序插件,如果想了解如何在uni-app中引用和使用小程序插件,另见文档:[使用小程序插件](/component/mp-weixin-plugin)
> 本文档意在介绍如何把uni-app项目编译为小程序插件,如果想了解如何在uni-app中引用和使用小程序插件,另见文档:[使用小程序插件](/tutorial/mp-weixin-plugin)
小程序插件规范由小程序厂商定义,插件是对一组 js 接口、自定义组件或页面的封装,用于嵌入到小程序中使用。
......@@ -88,7 +88,7 @@ plugin
1. `mp-weixin` 中的 `pages` 项与 `mp-alipay` 中的 `publicPages` 项作用一致
2. `mp-alipay` 中供外部使用的页面,需要在 `pages` 中声明,数组类型
3. 由于两端的格式不一致,可以在 `plugin.json` 中使用[条件编译](https://uniapp.dcloud.io/platform?id=preprocessor)处理
3. 由于两端的格式不一致,可以在 `plugin.json` 中使用[条件编译](https://uniapp.dcloud.io/tutorial/platform.html#preprocessor)处理
#### 编译步骤
......
......@@ -2,7 +2,7 @@
它类似微信小程序中`app.json`**页面管理**部分。注意定位权限申请等原属于`app.json`的内容,在uni-app中是在manifest中配置。
### 配置项列表
# 配置项列表
|属性|类型|必填|描述|平台兼容|
|:-|:-|:-|:-|:-|
......@@ -118,7 +118,7 @@
}
```
# globalStyle
## globalStyle
用于设置应用的状态栏、导航条、标题、窗口背景色等。
......@@ -130,15 +130,15 @@
|navigationStyle|String|default|导航栏样式,仅支持 default/custom。custom即取消默认的原生导航栏,需看[使用注意](/collocation/pages?id=customnav)|微信小程序 7.0+、百度小程序、H5、App(2.0.3+)|
|backgroundColor|HexColor|#ffffff|下拉显示出来的窗口的背景色|微信小程序|
|backgroundTextStyle|String|dark|下拉 loading 的样式,仅支持 dark / light|微信小程序|
|enablePullDownRefresh|Boolean|false|是否开启下拉刷新,详见[页面生命周期](/collocation/frame/lifecycle?id=页面生命周期)。||
|onReachBottomDistance|Number|50|页面上拉触底事件触发时距页面底部距离,单位只支持px,详见[页面生命周期](/collocation/frame/lifecycle?id=页面生命周期)||
|enablePullDownRefresh|Boolean|false|是否开启下拉刷新,详见[页面生命周期](/tutorial/page.html#lifecycle)。||
|onReachBottomDistance|Number|50|页面上拉触底事件触发时距页面底部距离,单位只支持px,详见[页面生命周期](/tutorial/page.html#lifecycle)||
|backgroundColorTop|HexColor|#ffffff|顶部窗口的背景色(bounce回弹区域)|仅 iOS 平台|
|backgroundColorBottom|HexColor|#ffffff|底部窗口的背景色(bounce回弹区域)|仅 iOS 平台|
|titleImage|String||导航栏图片地址(替换当前文字标题),支付宝小程序内必须使用https的图片链接地址|支付宝小程序、H5、APP|
|transparentTitle|String|none|导航栏整体(前景、背景)透明设置。支持 always 一直透明 / auto 滑动自适应 / none 不透明|支付宝小程序、H5、APP|
|titlePenetrate|String|NO|导航栏点击穿透|支付宝小程序、H5|
|pageOrientation|String|portrait|横屏配置,屏幕旋转设置,仅支持 auto / portrait / landscape 详见 [响应显示区域变化](https://developers.weixin.qq.com/miniprogram/dev/framework/view/resizable.html)|App 2.4.7+、微信小程序|
|animationType|String|pop-in|窗口显示的动画效果,详见:[窗口动画](api/router?id=animation)|App|
|animationType|String|pop-in|窗口显示的动画效果,详见:[窗口动画](/api/router?id=animation)|App|
|animationDuration|Number|300|窗口显示动画的持续时间,单位为 ms|App|
|app-plus|Object||设置编译到 App 平台的特定样式,配置项参考下方 [app-plus](/collocation/pages?id=app-plus)|App|
|h5|Object||设置编译到 H5 平台的特定样式,配置项参考下方 [H5](/collocation/pages?id=h5)|H5|
......@@ -149,7 +149,7 @@
|mp-lark|Object||设置编译到 mp-lark 平台的特定样式|飞书小程序|
|mp-qq|Object||设置编译到 mp-qq 平台的特定样式|QQ小程序|
|mp-kuaishou|Object||设置编译到 mp-kuaishou 平台的特定样式|快手小程序|
|usingComponents|Object| |引用小程序组件,参考 [小程序组件](/frame?id=小程序组件支持)||
|usingComponents|Object| |引用小程序组件,参考 [小程序组件](/tutorial/miniprogram-subject.html#小程序自定义组件支持)||
|renderingMode|String| |同层渲染,webrtc(实时音视频) 无法正常时尝试配置 seperated 强制关掉同层|微信小程序|
|leftWindow|Boolean|true|当存在 leftWindow 时,默认是否显示 leftWindow|H5|
|topWindow|Boolean|true|当存在 topWindow 时,默认是否显示 topWindow|H5|
......@@ -166,13 +166,13 @@
- `globalStyle`中设置的`titleImage`也会覆盖掉`pages`->`style`内的设置文字标题
- 使用 `maxWidth` 时,页面内fixed元素需要使用--window-left,--window-right来保证布局位置正确
# topWindow@topwindow
## topWindow@topwindow
uni-app 2.9+ 新增 leftWindow, topWindow, rightWindow 配置。用于解决宽屏适配问题。
以现有的手机应用为mainWindow,在左、上、右,可以追加新的页面显示窗体。
整体的宽屏适配思路,参考单独的[宽屏适配指南](https://uniapp.dcloud.net.cn/adapt)
整体的宽屏适配思路,参考单独的[宽屏适配指南](https://uniapp.dcloud.net.cn/tutorial/adapt)
|属性|类型|默认值|描述|
|:-|:-|:-|:-|
......@@ -250,18 +250,18 @@ uni-app 2.9+ 新增 leftWindow, topWindow, rightWindow 配置。用于解决宽
案例演示:HBuilderX 2.9.9+,新建项目选择hello uni-app或新闻模板,或直接浏览:[https://hellouniapp.dcloud.net.cn/](https://hellouniapp.dcloud.net.cn/)
# leftWindow
## leftWindow
[topWindow](/collocation/pages?id=topwindow)相同
# rightWindow
## rightWindow
[topWindow](/collocation/pages?id=topwindow)相同
窗口通信参考:[https://uniapp.dcloud.net.cn/api/window/communication](https://uniapp.dcloud.net.cn/api/window/communication)
# pages
## pages
`uni-app` 通过 pages 节点配置应用由哪些页面组成,pages 节点接收一个数组,数组每个项都是一个对象,其属性值如下:
......@@ -326,8 +326,8 @@ uni-app 2.9+ 新增 leftWindow, topWindow, rightWindow 配置。用于解决宽
|disableScroll|Boolean|false|设置为 true 则页面整体不能上下滚动(bounce效果),只在页面配置中有效,在globalStyle中设置无效|微信小程序(iOS)、百度小程序(iOS)|
|backgroundColor|HexColor|#ffffff|窗口的背景色|微信小程序、百度小程序、字节跳动小程序、飞书小程序|
|backgroundTextStyle|String|dark|下拉 loading 的样式,仅支持 dark/light||
|enablePullDownRefresh|Boolean|false|是否开启下拉刷新,详见[页面生命周期](/collocation/frame/lifecycle?id=页面生命周期)。||
|onReachBottomDistance|Number|50|页面上拉触底事件触发时距页面底部距离,单位只支持px,详见[页面生命周期](/collocation/frame/lifecycle?id=页面生命周期)||
|enablePullDownRefresh|Boolean|false|是否开启下拉刷新,详见[页面生命周期](/tutorial/page.html#lifecycle)。||
|onReachBottomDistance|Number|50|页面上拉触底事件触发时距页面底部距离,单位只支持px,详见[页面生命周期](/tutorial/page.html#lifecycle)||
|backgroundColorTop|HexColor|#ffffff|顶部窗口的背景色(bounce回弹区域)|仅 iOS 平台|
|backgroundColorBottom|HexColor|#ffffff|底部窗口的背景色(bounce回弹区域)|仅 iOS 平台|
|titleImage|String||导航栏图片地址(替换当前文字标题),支付宝小程序内必须使用https的图片链接地址|支付宝小程序、H5|
......@@ -342,7 +342,7 @@ uni-app 2.9+ 新增 leftWindow, topWindow, rightWindow 配置。用于解决宽
|mp-lark|Object||设置编译到 mp-lark 平台的特定样式|飞书小程序|
|mp-qq|Object||设置编译到 mp-qq 平台的特定样式|QQ小程序|
|mp-kuaishou|Object||设置编译到 mp-kuaishou 平台的特定样式|快手小程序|
|usingComponents|Object||引用小程序组件,参考 [小程序组件](/frame?id=小程序组件支持)|App、微信小程序、支付宝小程序、百度小程序|
|usingComponents|Object||引用小程序组件,参考 [小程序组件](/tutorial/miniprogram-subject.html#小程序自定义组件支持)|App、微信小程序、支付宝小程序、百度小程序|
|leftWindow|Boolean|true|当存在 leftWindow时,当前页面是否显示 leftWindow|H5|
|topWindow|Boolean|true|当存在 topWindow 时,当前页面是否显示 topWindow|H5|
|rightWindow|Boolean|true|当存在 rightWindow时,当前页面是否显示 rightWindow|H5|
......@@ -375,7 +375,7 @@ uni-app 2.9+ 新增 leftWindow, topWindow, rightWindow 配置。用于解决宽
### 自定义导航栏使用注意@customnav
当navigationStyle设为custom或titleNView设为false时,原生导航栏不显示,此时要注意几个问题:
- 非H5端,手机顶部状态栏区域会被页面内容覆盖。这是因为窗体是沉浸式的原因,即全屏可写内容。uni-app提供了状态栏高度的css变量[--status-bar-height](/frame?id=css%e5%8f%98%e9%87%8f),如果需要把状态栏的位置从前景部分让出来,可写一个占位div,高度设为css变量。
- 非H5端,手机顶部状态栏区域会被页面内容覆盖。这是因为窗体是沉浸式的原因,即全屏可写内容。uni-app提供了状态栏高度的css变量[--status-bar-height](/tutorial/syntax-css.html#css-变量),如果需要把状态栏的位置从前景部分让出来,可写一个占位div,高度设为css变量。
```html
<template>
<view>
......@@ -422,7 +422,7 @@ uni-app 2.9+ 新增 leftWindow, topWindow, rightWindow 配置。用于解决宽
|softinputMode|String|adjustPan|软键盘弹出模式,支持 adjustResize、adjustPan 两种模式|App|
|pullToRefresh|Object||下拉刷新|App|
|scrollIndicator|String||滚动条显示策略,设置为 "none" 时不显示滚动条。|App|
|animationType|String|pop-in|窗口显示的动画效果,详见:[窗口动画](api/router?id=animation)。|App|
|animationType|String|pop-in|窗口显示的动画效果,详见:[窗口动画](/api/router?id=animation)。|App|
|animationDuration|Number|300|窗口显示动画的持续时间,单位为 ms。|App|
**Tips**
- `.nvue` 页面仅支持 `titleNView、pullToRefresh、scrollIndicator` 配置,其它配置项暂不支持
......@@ -467,7 +467,7 @@ uni-app 2.9+ 新增 leftWindow, topWindow, rightWindow 配置。用于解决宽
- 页面支持通过配置 navigationStyle为custom,或titleNView为false,来禁用原生导航栏。一旦禁用原生导航,请注意阅读[自定义导航注意事项](/collocation/pages?id=customnav)
- `titleNView``type` 值为 `transparent` 时,导航栏为滚动透明渐变导航栏,默认只有button,滚动后标题栏底色和title文字会渐变出现; `type``float` 时,导航栏为悬浮标题栏,此时页面内容上顶到了屏幕顶部,包括状态栏,但导航栏悬浮盖在页面上方,一般这种场景会同时设置导航栏的背景色为rgba半透明颜色。
- `titleNView``type` 值为 `transparent` 时,App-nvue 2.4.4+ 支持
-`titleNView` 配置 `buttons` 后,监听按钮的点击事件,vue 页面及 nvue 的weex编译模式参考:[uni.onNavigationBarButtonTap](/nvue-outline?id=onnavigationbarbuttontap)
-`titleNView` 配置 `buttons` 后,监听按钮的点击事件,vue 页面及 nvue 的weex编译模式参考:[uni.onNavigationBarButtonTap](/tutorial/nvue-outline?id=onnavigationbarbuttontap)
-`titleNView` 配置 `searchInput` 后,相关的事件监听参考:[onNavigationBarSearchInputChanged 等](/collocation/frame/lifecycle?id=页面生命周期)
- 可通过 `[<navigation-bar>(/component/navigation-bar)]` 配置
- App下原生导航栏的按钮如果使用字体图标,注意检查字体库的名字(font-family)是否使用了默认的 iconfont,这个名字是保留字,不能作为外部引入的字体库的名字,需要调整为自定义的名称,否则无法显示。
......@@ -540,7 +540,7 @@ searchInput可以在titleNView的原生导航栏上放置搜索框。其宽度
**searchInput Tips**
searchInput的点击输入框onNavigationBarSearchInputClicked、文本变化onNavigationBarSearchInputChanged、点击搜索按钮onNavigationBarSearchInputConfirmed等生命周期,见文档[页面生命周期](/frame?id=%E9%A1%B5%E9%9D%A2%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F)
searchInput的点击输入框onNavigationBarSearchInputClicked、文本变化onNavigationBarSearchInputChanged、点击搜索按钮onNavigationBarSearchInputConfirmed等生命周期,见文档[页面生命周期](/tutorial/page.html#lifecycle)
- 在生命周期里通过参数e.text,可获取输入框内容。具体见hello uni-app中模板-顶部导航栏中的示例
- 如需动态修改searchInput,或者获取searchInput的placehold,参考[uni-app动态修改App端导航栏](https://ask.dcloud.net.cn/article/35374)
......@@ -760,17 +760,17 @@ searchInput的点击输入框onNavigationBarSearchInputClicked、文本变化onN
|属性|类型|默认值|描述|最低版本|
|:-|:-|:-|:-|:-|
|backgroundColor|String|#F7F7F7|背景颜色,颜色值格式为"#RRGGBB"。||
|buttons|Array||自定义按钮,参考 [buttons](collocation/pages?id=h5-titlenview-buttons)||
|buttons|Array||自定义按钮,参考 [buttons](#h5-titlenview-buttons)||
|titleColor|String|#000000|标题文字颜色||
|titleText|String||标题文字内容||
|titleSize|String||标题文字字体大小||
|type|String|default|导航栏样式。"default"-默认样式;"transparent"-透明渐变。||
|searchInput|Object||导航栏上的搜索框样式,详见:[searchInput](/collocation/pages?id=h5-searchInput)|1.6.5|
|searchInput|Object||导航栏上的搜索框样式,详见:[searchInput](#h5-searchinput)|1.6.5|
##### 自定义按钮@h5-titleNView-buttons
|属性|类型|默认值|描述|
|:-|:-|:-|:-|
|type|String|none|按钮样式,可取值见:[buttons 样式](collocation/pages?id=h5-titlenview-buttons-type)|
|type|String|none|按钮样式,可取值见:[buttons 样式](#app-titlenview-buttons-type)|
|color|String|默认与标题文字颜色一致|按钮上文字颜色|
|background|String|默认值为灰色半透明|按钮的背景颜色,仅在标题栏type=transparent时生效|
|badgeText|String||按钮上显示的角标文本,最多显示3个字符,超过则显示为...|
......@@ -858,7 +858,7 @@ h5 平台下拉刷新动画,只有 circle 类型。
- Q:如何取消原生导航栏?或自定义导航
- A:参考[导航栏开发指南](http://ask.dcloud.net.cn/article/34921)
# easycom
## easycom
> `HBuilderX 2.5.5`起支持`easycom`组件模式。
......@@ -921,7 +921,7 @@ h5 平台下拉刷新动画,只有 circle 类型。
- `easycom`只处理vue组件,不处理小程序专用组件(如微信的wxml格式组件)。不处理后缀为.nvue的组件。但vue组件也可以全端运行,包括小程序和app-nvue。可以参考uni ui,使用vue后缀,同时兼容nvue页面。
- `nvue`页面里引用`.vue`后缀的组件,会按照nvue方式使用原生渲染,其中不支持的css会被忽略掉。这种情况同样支持`easycom`
# tabBar
## tabBar
如果应用是一个多 tab 应用,可以通过 tabBar 配置项指定一级导航栏,以及 tab 切换时显示的对应页。
......@@ -977,9 +977,9 @@ midButton没有pagePath,需监听点击事件,自行处理点击后的行为
#### **tabbar常见问题** @tips-tabbar
- tabbar 的 js api 见[接口-界面-tabbar](https://uniapp.dcloud.io/api/ui/tabbar),可实现动态显示隐藏(如弹出层无法覆盖tabbar)、内容修改(如国际化)、item加角标等功能。hello uni-app中也有示例。
- tabbar 的 item 点击事件见[页面生命周期的onTabItemTap](https://uniapp.dcloud.io/collocation/frame/lifecycle?id=%E9%A1%B5%E9%9D%A2%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F)
- tabbar 的 item 点击事件见[页面生命周期的onTabItemTap](https://uniapp.dcloud.io/tutorial/page.html#lifecycle)
- 代码跳转到 tabbar 页面,api只能使用[uni.switchTab](https://uniapp.dcloud.io/api/router?id=switchtab),不能使用uni.navigateTo、uni.redirectTo;使用navigator组件跳转时必须设置[open-type="switchTab"](https://uniapp.dcloud.io/component/navigator)
- tabbar 的默认高度,在不同平台不一样。App端的默认高度在HBuilderX 2.3.4起从56px调整为50px,与H5端统一。开发者也可以自行设定高度,调回56px。[详见](https://uniapp.dcloud.io/frame?id=%e5%9b%ba%e5%ae%9a%e5%80%bc)
- tabbar 的默认高度,在不同平台不一样。App端的默认高度在HBuilderX 2.3.4起从56px调整为50px,与H5端统一。开发者也可以自行设定高度,调回56px。[详见](https://uniapp.dcloud.io/tutorial/syntax-css.html#固定值)
- tabbar 在H5端是div模拟的,属于前端屏幕窗口的一部分,如果要使用bottom居底定位方式,应该使用css变量`--window-bottom`,比如悬浮在tabbar上方10px的按钮,样式如下`bottom: calc(var(--window-bottom) + 10px)`
- 中间带+号的tabbar模板例子,[参考](https://ext.dcloud.net.cn/plugin?id=98)。可跨端,但+号不凸起。如需中间凸起,配置tabbar的midButton。
- 如果是需要先登录、后进入tab页面,不需要把登录页设为首页,首页仍然是tabbar页,可参考HBuilderX新建uni-app项目时的登录模板
......@@ -1028,7 +1028,7 @@ midButton没有pagePath,需监听点击事件,自行处理点击后的行为
- 原生的tabbar有且只有一个且在首页。二级页如需的tab,需自行编写view来实现。一般二级页面更适合的导航是 [segement组件](https://ext.dcloud.net.cn/plugin?id=54)
# condition
## condition
启动模式配置,仅开发期间生效,用于模拟直达页面的场景,如:小程序转发后,用户点击所打开的页面。
**属性说明:**
......@@ -1044,7 +1044,7 @@ midButton没有pagePath,需监听点击事件,自行处理点击后的行为
|:-|:-|:-|:-|
|name|String|是|启动模式名称|
|path|String|是|启动页面路径|
|query|String|否|启动参数,可在页面的 [onLoad](/collocation/frame/lifecycle?id=页面生命周期) 函数里获得|
|query|String|否|启动参数,可在页面的 [onLoad](/tutorial/page.html#lifecycle) 函数里获得|
**注意:** 在 App 里真机运行可直接打开配置的页面,微信开发者工具里需要手动改变编译模式,如下图:
......@@ -1070,7 +1070,7 @@ midButton没有pagePath,需监听点击事件,自行处理点击后的行为
}
```
# subPackages
## subPackages
分包加载配置,此配置为小程序的分包加载机制。
......@@ -1087,7 +1087,7 @@ subPackages 节点接收一个数组,数组每一项都是应用的子包,
|属性|类型|是否必填|描述|
|:-|:-|:-|:-|
|root|String|是|子包的根目录|
|pages|Array|是|子包由哪些页面组成,参数同 [pages](/collocation/pages?id=pages)|
|pages|Array|是|子包由哪些页面组成,参数同 [pages](#pages)|
**注意:**
......@@ -1166,7 +1166,7 @@ subPackages 节点接收一个数组,数组每一项都是应用的子包,
}
```
# preloadRule
## preloadRule
分包预载配置。
......@@ -1181,6 +1181,6 @@ subPackages 节点接收一个数组,数组每一项都是应用的子包,
app的分包,同样支持preloadRule,但网络规则无效。
# FAQ
## FAQ
- Q:为什么在pages.json里配置小程序定位权限描述,无法编译到小程序端,运行后一直提示getLocation需要在app.json中声明
- A:微信小程序的权限描述配置在manifest中,不在pages.json中,具体参考文档:[https://uniapp.dcloud.io/collocation/manifest?id=mp-weixin](https://uniapp.dcloud.io/collocation/manifest?id=mp-weixin)
......@@ -8,7 +8,7 @@
1. 如要使用这些常用变量,需要在 HBuilderX 里面安装 scss 插件;
2. 使用时需要在 style 节点上加上 ``lang="scss"``
```
```html
<style lang="scss">
</style>
```
......@@ -16,7 +16,7 @@
**以下是 uni.scss 的相关变量:**
```
```css
/* 颜色变量 */
/* 行为相关颜色 */
......
......@@ -10,7 +10,7 @@ vue.config.js 是一个可选的配置文件,如果项目的根目录中存在
部分配置项会被编译配置覆盖,例如:
* publicPath 不支持,如果需要配置,请在 manifest.json->h5->router->base 中配置,参考文档:[h5-router](collocation/manifest?id=h5-router)
* publicPath 不支持,如果需要配置,请在 manifest.json->h5->router->base 中配置,参考文档:[h5-router](/collocation/manifest?id=h5-router)
* outputDir 不支持
* assetsDir 固定 static
* pages 不支持
......
......@@ -67,9 +67,9 @@
|style|String|组件的内联样式|可以动态设置的内联样式|
|hidden|Boolean|组件是否隐藏|所有组件默认是显示的|
|data-*|Any|自定义属性|组件上触发的事件时,会发送给事件处理函数|
|@\*|EventHandler|组件的事件|详见各组件详细文档,事件绑定参考 [事件处理器](/vue-basics?id=事件处理器)|
|@\*|EventHandler|组件的事件|详见各组件详细文档,事件绑定参考 [事件处理器](/tutorial/vue-basics?id=事件处理器)|
除了上述公共属性,还有一类特殊属性以`v-`开头,称之为vue指令,如v-if、v-else、v-for、v-model。详见[vue指令](/vue-api?id=%e6%a8%a1%e6%9d%bf%e6%8c%87%e4%bb%a4)
除了上述公共属性,还有一类特殊属性以`v-`开头,称之为vue指令,如v-if、v-else、v-for、v-model。详见[vue指令](/tutorial/vue-api?id=%e6%a8%a1%e6%9d%bf%e6%8c%87%e4%bb%a4)
#### 在组件中使用js变量
......@@ -167,12 +167,12 @@ uni-app为开发者提供了一系列基础组件,类似HTML里的基础标签
|组件名|说明|
|:-|:-|
|[view](component/view.md)|视图容器,类似于HTML中的div|
|[scroll-view](component/scroll-view.md)|可滚动视图容器|
|[swiper](component/swiper.md)|滑块视图容器,比如用于轮播banner|
|[match-media](component/match-media.md)|屏幕动态适配组件,比如窄屏上不显示某些内容|
|[movable-area](component/movable-view.md?id=movable-area)|可拖动区域|
|[movable-view](component/movable-view.md?id=movable-view)|可移动的视图容器,在页面中可以拖拽滑动或双指缩放。movable-view必须在movable-area组件中|
|[view](/component/view.md)|视图容器,类似于HTML中的div|
|[scroll-view](/component/scroll-view.md)|可滚动视图容器|
|[swiper](/component/swiper.md)|滑块视图容器,比如用于轮播banner|
|[match-media](/component/match-media.md)|屏幕动态适配组件,比如窄屏上不显示某些内容|
|[movable-area](/component/movable-view.md?id=movable-area)|可拖动区域|
|[movable-view](/component/movable-view.md?id=movable-view)|可移动的视图容器,在页面中可以拖拽滑动或双指缩放。movable-view必须在movable-area组件中|
|[cover-view](/component/cover-view?id=cover-view)|可覆盖在原生组件的上的文本组件|
|[cover-image](/component/cover-view?id=cover-image)|可覆盖在原生组件的上的图片组件|
......@@ -180,83 +180,83 @@ uni-app为开发者提供了一系列基础组件,类似HTML里的基础标签
|组件名|说明|
|:-|:-|
|[icon](component/icon.md)|图标|
|[text](component/text.md)|文字|
|[rich-text](component/rich-text.md)|富文本显示组件|
|[progress](component/progress.md)|进度条|
|[icon](/component/icon.md)|图标|
|[text](/component/text.md)|文字|
|[rich-text](/component/rich-text.md)|富文本显示组件|
|[progress](/component/progress.md)|进度条|
**表单组件(Form):**
|标签名|说明|
|:-|:-|
|[button](component/button.md)|按钮|
|[checkbox](component/checkbox.md)|多项选择器|
|[editor](component/editor.md)|富文本输入框|
|[form](component/form.md)|表单|
|[input](component/input.md)|输入框|
|[label](component/label.md)|标签|
|[picker](component/picker.md)|弹出式列表选择器|
|[picker-view](component/picker-view.md)|窗体内嵌式列表选择器|
|[radio](component/radio.md)|单项选择器|
|[slider](component/slider.md)|滑动选择器|
|[switch](component/switch.md)|开关选择器|
|[textarea](component/textarea.md)|多行文本输入框|
|[button](/component/button.md)|按钮|
|[checkbox](/component/checkbox.md)|多项选择器|
|[editor](/component/editor.md)|富文本输入框|
|[form](/component/form.md)|表单|
|[input](/component/input.md)|输入框|
|[label](/component/label.md)|标签|
|[picker](/component/picker.md)|弹出式列表选择器|
|[picker-view](/component/picker-view.md)|窗体内嵌式列表选择器|
|[radio](/component/radio.md)|单项选择器|
|[slider](/component/slider.md)|滑动选择器|
|[switch](/component/switch.md)|开关选择器|
|[textarea](/component/textarea.md)|多行文本输入框|
**路由与页面跳转(Navigation):**
|组件名|说明|
|:-|:-|
|[navigator](component/navigator.md)|页面链接。类似于HTML中的a标签|
|[navigator](/component/navigator.md)|页面链接。类似于HTML中的a标签|
**媒体组件(Media):**
|组件名|说明|
|:-|:-|
|[audio](component/audio.md)|音频|
|[camera](component/camera.md)|相机|
|[image](component/image.md)|图片|
|[video](component/video.md)|视频|
|[live-player](component/live-player.md)|直播播放|
|[live-pusher](component/live-pusher.md)|实时音视频录制,也称直播推流|
|[audio](/component/audio.md)|音频|
|[camera](/component/camera.md)|相机|
|[image](/component/image.md)|图片|
|[video](/component/video.md)|视频|
|[live-player](/component/live-player.md)|直播播放|
|[live-pusher](/component/live-pusher.md)|实时音视频录制,也称直播推流|
**地图(Map):**
|组件名|说明|
|:-|:-|
|[map](component/map.md)|地图|
|[map](/component/map.md)|地图|
**画布(Canvas):**
|组件名|说明|
|:-|:-|
|[canvas](component/canvas.md)|画布|
|[canvas](/component/canvas.md)|画布|
**webview(Web-view):**
|组件名|说明|
|:-|:-|
|[web-view](component/web-view.md)|web浏览器组件|
|[web-view](/component/web-view.md)|web浏览器组件|
**广告**
|组件名|说明|
|:-|:-|
|[ad](component/ad.md)|广告组件|
|[ad-draw](component/ad-draw.md)|沉浸视频流广告组件|
|[ad](/component/ad.md)|广告组件|
|[ad-draw](/component/ad-draw.md)|沉浸视频流广告组件|
**页面属性配置**
|组件名|说明|
|:-|:-|
|[custom-tab-bar](component/custom-tab-bar.md)|底部tabbar自定义组件|
|[navigation-bar](component/navigation-bar.md)|页面顶部导航|
|[page-meta](component/page-meta.md)|页面属性配置节点|
|[custom-tab-bar](/component/custom-tab-bar.md)|底部tabbar自定义组件|
|[navigation-bar](/component/navigation-bar.md)|页面顶部导航|
|[page-meta](/component/page-meta.md)|页面属性配置节点|
**uniCloud**
|组件名|说明|
|:-|:-|
|[unicloud-db组件](uniCloud/unicloud-db)|uniCloud数据库访问和操作组件|
|[unicloud-db组件](/uniCloud/unicloud-db)|uniCloud数据库访问和操作组件|
**各平台专有组件**
......@@ -291,8 +291,8 @@ uni-app为开发者提供了一系列基础组件,类似HTML里的基础标签
uni-app支持的组件分为vue组件和小程序自定义组件。
如果你还不了解这两种组件,可以参阅各自的文档
- vue组件:[文档](https://uniapp.dcloud.net.cn/vue-components?id=%e6%a6%82%e5%bf%b5)
- 小程序自定义组件:其规范不是vue规范,而是小程序规范,[文档](https://uniapp.dcloud.net.cn/frame?id=%e5%b0%8f%e7%a8%8b%e5%ba%8f%e8%87%aa%e5%ae%9a%e4%b9%89%e7%bb%84%e4%bb%b6%e6%94%af%e6%8c%81)
- vue组件:[文档](https://uniapp.dcloud.net.cn/tutorial/vue-components?id=%e6%a6%82%e5%bf%b5)
- 小程序自定义组件:其规范不是vue规范,而是小程序规范,[文档](https://uniapp.dcloud.net.cn/tutorial/miniprogram-subject.html#小程序自定义组件支持)
日常开发来讲,推荐使用vue组件。uni-app支持小程序组件主要是为了兼容更多生态资源。
......@@ -374,7 +374,7 @@ uni_module其实不止服务于组件,它可以服务于组件、js库、页
uni_module还支持云端一体的插件。
uni_module有详细的专项文档,请另行查阅[uni_module规范](/uni_modules)
uni_module有详细的专项文档,请另行查阅[uni_module规范](/plugin/uni_modules.html)
### uniCloud组件
......@@ -384,7 +384,7 @@ uni-app的基础组件中,有一个特殊基础组件是:`<unicloud-db>`组
它可以在前端直接获取和操作uniCloud的云端数据库。
相关文档详见:[unicloud-db组件](uniCloud/unicloud-db)
相关文档详见:[unicloud-db组件](/uniCloud/unicloud-db)
除了内置的数据库组件,在uni-ui扩展库里还有uniCloud的文件选择和上传组件,参考:[uni-file-picker](https://ext.dcloud.net.cn/plugin?id=4079)
......@@ -427,7 +427,7 @@ datacom组件是一种数据驱动的、可云端一体的组件。
### 扩展组件(uni-ui)@uniui
详见: [uni-ui介绍](component/uniui/uni-ui.md)
详见: [uni-ui介绍](/component/uniui/uni-ui.md)
**更多组件**
......
* [组件概述](component/)
* [vue组件](component/vue-component.md)
* 视图容器
* [view](component/view.md)
* [scroll-view](component/scroll-view.md)
* [swiper](component/swiper.md)
* [match-media](component/match-media.md)
* [movable-area](component/movable-view.md?id=movable-area)
* [movable-view](component/movable-view.md?id=movable-view)
* [cover-view](/component/cover-view?id=cover-view)
* [cover-image](/component/cover-view?id=cover-image)
* 基础内容
* [icon](component/icon.md)
* [text](component/text.md)
* [rich-text](component/rich-text.md)
* [progress](component/progress.md)
* 表单组件
* [button](component/button.md)
* [checkbox](component/checkbox.md)
* [editor](component/editor.md)
* [form](component/form.md)
* [input](component/input.md)
* [label](component/label.md)
* [picker](component/picker.md)
* [picker-view](component/picker-view.md)
* [radio](component/radio.md)
* [slider](component/slider.md)
* [switch](component/switch.md)
* [textarea](component/textarea.md)
* 路由与页面跳转
* [navigator](component/navigator.md)
* 媒体组件
* [audio](component/audio.md)
* [camera](component/camera.md)
* [image](component/image.md)
* [video](component/video.md)
* [live-player](component/live-player.md)
* [live-pusher](component/live-pusher.md)
* 地图
* [map](component/map.md)
* 画布
* [canvas](component/canvas.md)
* webview
* [web-view](component/web-view.md)
* 广告
* [ad](component/ad.md)
* [ad-draw](component/ad-draw.md)
* [ad-content-page](component/ad-content-page.md)
* [Grid 广告](component/ad-grid.md)
* 页面属性配置节点
* [page-meta](component/page-meta.md)
* [navigation-bar](component/navigation-bar.md)
* [custom-tab-bar](component/custom-tab-bar.md)
* 小程序开放能力组件
* [official-account](component/official-account.md)
* [open-data](component/open-data.md)
* App nvue专用组件
* [barcode](component/barcode.md)
* [list](component/list.md)
* [cell](component/cell.md)
* [recycle-list](component/recycle-list.md)
* [waterfall](component/waterfall.md)
* [refresh](component/refresh.md)
* uniCloud专用组件
* [unicloud-db](uniCloud/unicloud-db)
* [基础组件中原生组件说明](component/native-component.md)
* 扩展组件(uni-ui)
* [介绍](component/uniui/uni-ui.md)
* [开始使用](component/uniui/quickstart.md)
* [资源下载](component/uniui/resource.md)
* [色彩说明](component/uniui/color.md)
* [uni-sass 辅助样式](component/uniui/uni-sass.md)
* [uni-badge 数字角标](component/uniui/uni-badge.md)
* [uni-calendar 日历](component/uniui/uni-calendar.md)
* [uni-card 卡片](component/uniui/uni-card.md)
* [uni-collapse 折叠面板](component/uniui/uni-collapse.md)
* [uni-combox 组合框](component/uniui/uni-combox.md)
* [uni-countdown 倒计时](component/uniui/uni-countdown.md)
* [uni-data-checkbox 数据选择器](component/uniui/uni-data-checkbox.md)
* [uni-data-picker 数据驱动的picker选择器](component/uniui/uni-data-picker.md)
* [uni-dateformat 日期格式化](component/uniui/uni-dateformat.md)
* [uni-datetime-picker 日期选择器](component/uniui/uni-datetime-picker.md)
* [uni-drawer 抽屉](component/uniui/uni-drawer.md)
* [uni-easyinput 增强输入框](component/uniui/uni-easyinput.md)
* [uni-fab 悬浮按钮](component/uniui/uni-fab.md)
* [uni-fav 收藏按钮](component/uniui/uni-fav.md)
* [uni-file-picker 文件选择上传](component/uniui/uni-file-picker.md)
* [uni-forms 表单](component/uniui/uni-forms.md)
* [uni-goods-nav 商品导航](component/uniui/uni-goods-nav.md)
* [uni-grid 宫格](component/uniui/uni-grid.md)
* [uni-group 分组](component/uniui/uni-group.md)
* [uni-icons 图标](component/uniui/uni-icons.md)
* [uni-indexed-list 索引列表](component/uniui/uni-indexed-list.md)
* [uni-link 超链接](component/uniui/uni-link.md)
* [uni-list 列表](component/uniui/uni-list.md)
* [uni-load-more 加载更多](component/uniui/uni-load-more.md)
* [uni-nav-bar 自定义导航栏](component/uniui/uni-nav-bar.md)
* [uni-notice-bar 通告栏](component/uniui/uni-notice-bar.md)
* [uni-number-box 数字输入框](component/uniui/uni-number-box.md)
* [uni-pagination 分页器](component/uniui/uni-pagination.md)
* [uni-popup 弹出层](component/uniui/uni-popup.md)
* [uni-rate 评分](component/uniui/uni-rate.md)
* [uni-row 布局-行](component/uniui/uni-row.md)
* [uni-search-bar 搜索栏](component/uniui/uni-search-bar.md)
* [uni-segmented-control 分段器](component/uniui/uni-segmented-control.md)
* [uni-steps 步骤条](component/uniui/uni-steps.md)
* [uni-swipe-action 滑动操作](component/uniui/uni-swipe-action.md)
* [uni-swiper-dot 轮播图指示点](component/uniui/uni-swiper-dot.md)
* [uni-table 表格](component/uniui/uni-table.md)
* [uni-tag 标签](component/uniui/uni-tag.md)
* [uni-title 章节标题](component/uniui/uni-title.md)
* [uni-transition 过渡动画](component/uniui/uni-transition.md)
* [更新日志](https://ext.dcloud.net.cn/plugin?id=55&update_log)
* [更多插件市场的组件](https://ext.dcloud.net.cn/?cat1=2)
* [datacom组件规范](component/datacom)
* [App原生插件](https://nativesupport.dcloud.net.cn/NativePlugin/README)
* [小程序插件](component/mp-weixin-plugin.md)
<li></li>
<div class="contact-box">
<a href="//unicloud.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/7962e8e0-4f2d-11eb-a16f-5b3e54966275.jpg" width="20" height="20"/>
<div class="contact-smg">
<div>uniCloud Web控制台</div>
</div>
</a>
<a href="//ask.dcloud.net.cn/explore/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/73fc4f90-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>论坛</div>
</div>
</a>
<a href="https://uniad.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/765d9820-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>uniAD</div>
</div>
</a>
<a href="https://tongji.dcloud.net.cn/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77159d80-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>uni统计</div>
</div>
</a>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/74cda950-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>
代码仓库:<a href="https://gitee.com/dcloud/uni-app" target="_blank">码云</a><a href="http://github.com/dcloudio/uni-app" target="_blank">GitHub</a>
</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/759713d0-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>官方QQ交流群</div>
<div>群3:773794803 &nbsp;<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=kEhCLZ5s4OhcFqHnD938uR_QOGK21xO4&jump_from=webapi">点此加入</a></div>
<div>群35:713420817(2000人已满)</div>
<div>群34:530305531(2000人已满)</div>
<div>群33:498071674(2000人已满)</div>
<div>群32:166188631(2000人已满)</div>
<div>群31:567471669(2000人已满)</div>
<div>群30:371046920(2000人已满)</div>
<div>群29:202965481(2000人已满)</div>
<div>群28:166188776(2000人已满)</div>
<div>群27:811363410(2000人已满)</div>
<div>群26:147867597(2000人已满)</div>
<div>群25:165297000(2000人已满)</div>
<div>群24:672494800(2000人已满)</div>
<div>群23:599958679(2000人已满)</div>
<div>群22:687186952(2000人已满)</div>
<div>群21:717019120(2000人已满)</div>
<div>群20:165796402(2000人已满)</div>
<div>群19:165657124(2000人已满)</div>
<div>群18:698592271(2000人已满)</div>
<div>群17:951348804(2000人已满)</div>
<div>群16:719211033(2000人已满)</div>
<div>群15:516984120(2000人已满)</div>
<div>群14:465953250(2000人已满)</div>
<div>群13:699478442(2000人已满)</div>
<div>群12:884860657(2000人已满)</div>
<div>群11:296811328(2000人已满)</div>
<div>群10:959059626(2000人已满)</div>
<div>群9:775128777(2000人已满)</div>
<div>群8:695442854(2000人已满)</div>
<div>群7:942061423(2000人已满)</div>
<div>群6:697264024(2000人已满)</div>
<div>群5:731951419(2000人已满)</div>
<div>群4:942702595(2000人已满)</div>
<!-- <div>群3:773794803(2000人已满) </div> -->
<div>群2:901474938(2000人已满) </div>
<div>群1:531031261(2000人已满)</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77df7d30-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>关注微信公众号</div>
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/78a8e7b0-4f2d-11eb-8ff1-d5dcf8779628.jpg" width="90" height="90"/>
</div>
</div>
</div>
* [组件概述](component/)
* [vue组件](component/vue-component.md)
* 视图容器
* [view](component/view.md)
* [scroll-view](component/scroll-view.md)
* [swiper](component/swiper.md)
* [match-media](component/match-media.md)
* [movable-area](component/movable-view.md?id=movable-area)
* [movable-view](component/movable-view.md?id=movable-view)
* [cover-view](/component/cover-view?id=cover-view)
* [cover-image](/component/cover-view?id=cover-image)
* 基础内容
* [icon](component/icon.md)
* [text](component/text.md)
* [rich-text](component/rich-text.md)
* [progress](component/progress.md)
* 表单组件
* [button](component/button.md)
* [checkbox](component/checkbox.md)
* [editor](component/editor.md)
* [form](component/form.md)
* [input](component/input.md)
* [label](component/label.md)
* [picker](component/picker.md)
* [picker-view](component/picker-view.md)
* [radio](component/radio.md)
* [slider](component/slider.md)
* [switch](component/switch.md)
* [textarea](component/textarea.md)
* 路由与页面跳转
* [navigator](component/navigator.md)
* 媒体组件
* [audio](component/audio.md)
* [camera](component/camera.md)
* [image](component/image.md)
* [video](component/video.md)
* [live-player](component/live-player.md)
* [live-pusher](component/live-pusher.md)
* 地图
* [map](component/map.md)
* 画布
* [canvas](component/canvas.md)
* webview
* [web-view](component/web-view.md)
* 广告
* [ad](component/ad.md)
* [ad-draw](component/ad-draw.md)
* [ad-content-page](component/ad-content-page.md)
* [Grid 广告](component/ad-grid.md)
* 页面属性配置节点
* [page-meta](component/page-meta.md)
* [navigation-bar](component/navigation-bar.md)
* [custom-tab-bar](component/custom-tab-bar.md)
* 小程序开放能力组件
* [official-account](component/official-account.md)
* [open-data](component/open-data.md)
* App nvue专用组件
* [barcode](component/barcode.md)
* [list](component/list.md)
* [cell](component/cell.md)
* [recycle-list](component/recycle-list.md)
* [waterfall](component/waterfall.md)
* [refresh](component/refresh.md)
* uniCloud专用组件
* [unicloud-db](uniCloud/unicloud-db)
* [基础组件中原生组件说明](component/native-component.md)
* 基础组件清单
* [uni-app 基础组件清单](component/view.md)
* [视图容器](component/view.md)
* [view](component/view.md)
* [scroll-view](component/scroll-view.md)
* [swiper](component/swiper.md)
* [match-media](component/match-media.md)
* [movable-area](component/movable-view.md?id=movable-area)
* [movable-view](component/movable-view.md?id=movable-view)
* [cover-view](/component/cover-view?id=cover-view)
* [cover-image](/component/cover-view?id=cover-image)
* [基础内容](component/icon.md)
* [icon](component/icon.md)
* [text](component/text.md)
* [rich-text](component/rich-text.md)
* [progress](component/progress.md)
* [表单组件](component/button.md)
* [button](component/button.md)
* [checkbox](component/checkbox.md)
* [editor](component/editor.md)
* [form](component/form.md)
* [input](component/input.md)
* [label](component/label.md)
* [picker](component/picker.md)
* [picker-view](component/picker-view.md)
* [radio](component/radio.md)
* [slider](component/slider.md)
* [switch](component/switch.md)
* [textarea](component/textarea.md)
* [路由与页面跳转](component/navigator.md)
* [navigator](component/navigator.md)
* [媒体组件](component/audio.md)
* [audio](component/audio.md)
* [camera](component/camera.md)
* [image](component/image.md)
* [video](component/video.md)
* [live-player](component/live-player.md)
* [live-pusher](component/live-pusher.md)
* [地图](component/map.md)
* [map](component/map.md)
* [画布](component/canvas.md)
* [canvas](component/canvas.md)
* [webview](component/web-view.md)
* [web-view](component/web-view.md)
* [广告](component/ad.md)
* [ad](component/ad.md)
* [ad-draw](component/ad-draw.md)
* [ad-content-page](component/ad-content-page.md)
* [Grid 广告](component/ad-grid.md)
* [页面属性配置节点](component/page-meta.md)
* [page-meta](component/page-meta.md)
* [navigation-bar](component/navigation-bar.md)
* [custom-tab-bar](component/custom-tab-bar.md)
* [基础组件中原生组件说明](component/native-component.md)
* [vue组件](component/vue-component.md)
* [NVUE 内置组件](component/barcode.md)
* [barcode](component/barcode.md)
* [list](component/list.md)
* [cell](component/cell.md)
* [recycle-list](component/recycle-list.md)
* [waterfall](component/waterfall.md)
* [refresh](component/refresh.md)
* [小程序内置组件](component/official-account.md)
* [official-account](component/official-account.md)
* [open-data](component/open-data.md)
* 扩展组件(uni-ui)
* [介绍](component/uniui/uni-ui.md)
* [开始使用](component/uniui/quickstart.md)
* [资源下载](component/uniui/resource.md)
* [色彩说明](component/uniui/color.md)
* [uni-sass 辅助样式](component/uniui/uni-sass.md)
* [uni-badge 数字角标](component/uniui/uni-badge.md)
......@@ -112,90 +111,6 @@
* [uni-transition 过渡动画](component/uniui/uni-transition.md)
* [更新日志](https://ext.dcloud.net.cn/plugin?id=55&update_log)
* [更多插件市场的组件](https://ext.dcloud.net.cn/?cat1=2)
* [datacom组件规范](component/datacom)
* [App原生插件](https://nativesupport.dcloud.net.cn/NativePlugin/README)
* [小程序插件](component/mp-weixin-plugin.md)
<li></li>
<div class="contact-box">
<a href="//unicloud.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/7962e8e0-4f2d-11eb-a16f-5b3e54966275.jpg" width="20" height="20"/>
<div class="contact-smg">
<div>uniCloud Web控制台</div>
</div>
</a>
<a href="//ask.dcloud.net.cn/explore/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/73fc4f90-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>论坛</div>
</div>
</a>
<a href="https://uniad.dcloud.net.cn" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/765d9820-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>uniAD</div>
</div>
</a>
<a href="https://tongji.dcloud.net.cn/" target="_blank" class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77159d80-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>uni统计</div>
</div>
</a>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/74cda950-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>
代码仓库:<a href="https://gitee.com/dcloud/uni-app" target="_blank">码云</a><a href="http://github.com/dcloudio/uni-app" target="_blank">GitHub</a>
</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/759713d0-4f2d-11eb-a16f-5b3e54966275.png" width="20" height="20"/>
<div class="contact-smg">
<div>官方QQ交流群</div>
<div>群3:773794803 &nbsp;<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=kEhCLZ5s4OhcFqHnD938uR_QOGK21xO4&jump_from=webapi">点此加入</a></div>
<div>群35:713420817(2000人已满)</div>
<div>群34:530305531(2000人已满)</div>
<div>群33:498071674(2000人已满)</div>
<div>群32:166188631(2000人已满)</div>
<div>群31:567471669(2000人已满)</div>
<div>群30:371046920(2000人已满)</div>
<div>群29:202965481(2000人已满)</div>
<div>群28:166188776(2000人已满)</div>
<div>群27:811363410(2000人已满)</div>
<div>群26:147867597(2000人已满)</div>
<div>群25:165297000(2000人已满)</div>
<div>群24:672494800(2000人已满)</div>
<div>群23:599958679(2000人已满)</div>
<div>群22:687186952(2000人已满)</div>
<div>群21:717019120(2000人已满)</div>
<div>群20:165796402(2000人已满)</div>
<div>群19:165657124(2000人已满)</div>
<div>群18:698592271(2000人已满)</div>
<div>群17:951348804(2000人已满)</div>
<div>群16:719211033(2000人已满)</div>
<div>群15:516984120(2000人已满)</div>
<div>群14:465953250(2000人已满)</div>
<div>群13:699478442(2000人已满)</div>
<div>群12:884860657(2000人已满)</div>
<div>群11:296811328(2000人已满)</div>
<div>群10:959059626(2000人已满)</div>
<div>群9:775128777(2000人已满)</div>
<div>群8:695442854(2000人已满)</div>
<div>群7:942061423(2000人已满)</div>
<div>群6:697264024(2000人已满)</div>
<div>群5:731951419(2000人已满)</div>
<div>群4:942702595(2000人已满)</div>
<!-- <div>群3:773794803(2000人已满) </div> -->
<div>群2:901474938(2000人已满) </div>
<div>群1:531031261(2000人已满)</div>
</div>
</div>
<div class="contact-item">
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/77df7d30-4f2d-11eb-bd01-97bc1429a9ff.png" width="20" height="20"/>
<div class="contact-smg">
<div>关注微信公众号</div>
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/78a8e7b0-4f2d-11eb-8ff1-d5dcf8779628.jpg" width="90" height="90"/>
</div>
</div>
</div>
* [ui 设计资源](component/uniui/resource.md)
* [datacom 组件规范](component/datacom.md)
* [组件库选型指南](component/component-selection.md)
\ No newline at end of file
......@@ -87,13 +87,13 @@ Grid 广告在创建后会自动拉取广告。开发者可以通过 ad 组件
广告组件提供黑、白两种主题样式,开发者可以在创建广告时传入ad-theme参数实现主题样式选择,ad-theme参数为字符串类型,参数值可选white, black
```
```html
<view class="adContainer">
<ad unit-id="xxxx" ad-type="grid" ad-theme="white"></ad>
</view>
```
```
```html
<view class="adContainer">
<ad unit-id="xxxx" ad-type="grid" ad-theme="black"></ad>
</view>
......@@ -104,13 +104,13 @@ Grid 广告在创建后会自动拉取广告。开发者可以通过 ad 组件
广告组件提供黑、白两种主题样式,开发者可以在创建广告时传入grid-count参数实现主题样式选择,grid-count参数为数字类型,参数值可选5, 8
```
```html
<view class="adContainer">
<ad unit-id="xxxx" ad-type="grid" grid-count="5"></ad>
</view>
```
```
```html
<view class="adContainer">
<ad unit-id="xxxx" ad-type="grid" grid-count="8"></ad>
</view>
......
......@@ -24,7 +24,7 @@
* canvas 在微信小程序、百度小程序、QQ小程序中为原生组件,层级高于前端组件,请勿内嵌在 scroll-view、swiper、picker-view、movable-view 中使用。解决 canvas 层级过高无法覆盖,参考 [native-component](/component/native-component)。其他小程序端的 canvas 仍然为 webview 中的 canvas。
* app-vue 中的 canvas 仍然是 webview 的 canvas。app-nvue下如需使用canvas,需下载插件,详见文档底部章节。
* app-vue的canvas虽然是webview自带的canvas,但却比nvue和微信小程序的原生canvas性能更高。注意并非原生=更快。canvas动画的流畅,关键不在于渲染引擎的速度,而在于减少从逻辑层向视图层频繁通信造成的折损。
* 小程序、app-nvue,因为通信阻塞,难以绘制非常流畅的canvas动画。h5和app-vue不存在此问题。但注意,app-vue下若想流畅的绘制canvas动画,需要使用[renderjs](https://uniapp.dcloud.io/frame?id=renderjs)技术,把操作canvas的js逻辑放到视图层运行,避免逻辑层和视图层频繁通信。hello uni-app的canvas示例很典型,在相同手机运行该示例,可以看出在h5端和app端非常流畅,而小程序端由于没有renderjs技术,做不到这么流畅的动画。
* 小程序、app-nvue,因为通信阻塞,难以绘制非常流畅的canvas动画。h5和app-vue不存在此问题。但注意,app-vue下若想流畅的绘制canvas动画,需要使用[renderjs](https://uniapp.dcloud.io/tutorial/renderjs?id=renderjs)技术,把操作canvas的js逻辑放到视图层运行,避免逻辑层和视图层频繁通信。hello uni-app的canvas示例很典型,在相同手机运行该示例,可以看出在h5端和app端非常流畅,而小程序端由于没有renderjs技术,做不到这么流畅的动画。
**示例:** [查看演示](https://hellouniapp.dcloud.net.cn/pages/component/canvas/canvas)
......@@ -68,7 +68,7 @@ export default {
}
```
相关 api:[uni.createCanvasContext](api/canvas/createCanvasContext)
相关 api:[uni.createCanvasContext](/api/canvas/createCanvasContext)
**扩展阅读**
......
### 组件的概念
组件是现代开发的重要里程碑。组件重构了分工模型,让大量的轮子出现,让开发者可以拿来轮子直接用,大幅提升了整个产业的效率。
uni-app是有[内置组件](https://uniapp.dcloud.io/component/README)的。这和web开发不一样。
web开发基本上不用基础组件,都是找一个三方ui库,全套组件都包含。那是因为html的基础组件默认样式不适配手机风格。
但uni-app体系不是这样,内置组件就是为手机优化的。
但内置组件只能满足基础需求,更多场景,需要扩展组件。
扩展组件是基于内置组件的二次封装,从性能上来讲,扩展组件的性能略低于内置组件,所以开发者切勿抛弃内置组件,直接全套用三方UI组件库。
uni-app的[插件市场](https://ext.dcloud.net.cn/),有很多扩展组件,有的是单独的,有的是成套的。
有些开发者喜欢成套的组件,但注意成套扩展组件也不可能覆盖所有需求,很多场景还是需要单独下载专业组件。
### 扩展组件的选择
众多扩展组件如何选择?我们首先要搞清楚组件的分类。
组件分2大类:1、vue组件(文件后缀为vue);2、小程序自定义组件(文件后缀为wxml或其他小程序平台特有后缀名称)
- vue组件又分为2个细项:only for web、全端兼容
- 小程序组件又分为:微信/QQ小程序组件、阿里小程序组件、百度小程序组件、字节跳动小程序组件。
这些组件uni-app都支持,但受组件本身技术特点限制,在不同端有不一样的支持度。
下面这张表格,可以清楚的表达不同类型的组件的兼容性。
[attach]52971[/attach]
从表格中可以很明显看出,更推荐使用的是全端兼容的uni规范组件。
很多人容易搞错2个问题:
1. 同样是vue组件,only for web的和全端的有什么区别?
传统的vue组件,比如elementUI,都是only for web的,里面有大量dom和window对象操作。但小程序和App是没有dom这些api的,自然无法跨端使用。
想要跨端,其实也不难,做一套无dom的vue组件即可。官方的uni-ui即是如此。还有众多开发者在插件市场提交了更多这种类型的库。
2. vant是分web版和weapp版的,千万别搞混
vant的web版操作了dom,所以只能用于web端;而vant weapp是微信小程序组件规范,可以用于微信、App、H5;vant自身并没有提供全端可用的无dom vue组件。
除了兼容性,在性能和生态完善度层面,不同类型组件有什么差别?
1. 性能:
- vue组件性能好于小程序自定义组件。这是因为uni-app在底层对vue数据更新使用了自动差量更新的机制。而小程序自定义组件,默认的setData写法是没有差量数据更新的,需要写代码手动实现差量更新才能达到相同性能。
2. 生态完善度
- 首先除了微信小程序,其他几个平台的小程序几乎是没有三方组件和模板生态的。开发其他端小程序,得靠uni-app的生态
- 再说微信小程序生态,之前在微信小程序平台上一些有名的库(比如wxParse、wx-Echart),实际上在性能、功能、技术支持上,大多做的不如uni-app生态下的新库好。而vant、iview的weapp版,其性能也均不如uni ui。
3. 其他指标
- vue doc:HBuilderX支持[vue doc](https://ask.dcloud.net.cn/article/35814),组件作者在vue组件源码里编写vue doc,可以让组件使用者写代码时得到良好的代码提示。
- easycom:uni-app支持[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom),可以大幅简化组件的使用
- nvue支持:如果开发App,可能会涉及到nvue原生渲染页面,这种渲染方式支持的css有限,此时就要甄别组件是否兼容nvue。
再来看看各种成套UI的优劣分析
#### uni ui
DCloud官方出了一套扩展组件,即[uni-ui](https://uniapp.dcloud.io/component/uniui/uni-ui)
这些扩展组件支持单个组件从插件市场下载,也支持[npm引入](https://ext.dcloud.net.cn/plugin?id=55)uni ui,当然更方便的是在HBuilderX新建项目时直接选择`uni ui项目模板`
uni ui有如下优势:
1. 优化逻辑层和视图层的通信折损:非H5端的各个平台,包括App和各种小程序,其逻辑层和视图层是分离的,两层之间通信交互会有折损,导致诸如跟手滑动不流畅。uni ui在底层会利用wxs等技术,把适当的js代码运行在视图层,减少通信折损,保证诸如swiperAction左滑菜单等跟手操作流畅顺滑
2. 自动差量diff数据:在uni-app下,开发App和小程序,不需要手动setData,底层自动会差量更新数据。但如果使用了小程序组件,则需要按小程序的setData方式来更新数据,很难做到自动diff更新数据。
3. 背景停止:很多ui组件是会一直动的,比如轮播图、跑马灯。即便这个窗体被新窗体挡住,它在背景层仍然在消耗着硬件资源。在Android的webview版本为chrome66以上,背景操作ui会引发很严重的性能问题,造成前台界面明显卡顿。而uni ui的组件,会自动判断自己的显示状态,在组件不再可见时,不会再做动画消耗硬件资源。
4. 纯vue语法:uni ui的引用、开发都是纯vue方式。而小程序组件的引用注册、开发都是小程序语法,两种语法混合在一个工程,写的也不舒服,维护也麻烦。
5.[uni统计](https://tongji.dcloud.net.cn)自动整合:比如使用uni ui的导航栏组件,就不需要写统计的自定义事件来触发页面标题上报。uni统计会自动识别导航栏组件的标题。类似的,收藏组件、购物车组件,都可以免打点直接使用。
6. uni ui兼容Android 4.4等低端机webview,没有浏览器兼容问题。
7. uni ui支持nvue:App端,uni-app同时支持webview渲染和原生渲染,而uni ui是可以一套代码同时支持webview渲染和原生渲染的。为了兼容原生渲染,uni ui也做到了纯flex布局。
8. uni ui内置vue doc,使用组件时有良好的代码提示
9. 支持[easycom](https://uniapp.dcloud.net.cn/collocation/pages?id=easycom)规范,使用非常简单
10. 支持[datacom规范](https://uniapp.dcloud.net.cn/component/datacom),云端一体全部封装掉
11. 支持[uni_module规范](https://uniapp.dcloud.net.cn/uni_modules),方便插件的更新
推荐在HBuilderX新建项目时,直接选择uni ui项目模板,然后在代码里直接敲u,所有组件都拉出来,不用引用、不用注册,直接就用。
[attach]53180[/attach]
![](http://img.cdn.aliyun.dcloud.net.cn/uni-app/doc/uni-ui-snippet.jpg)
#### 插件市场更多组件
插件市场,[https://ext.dcloud.net.cn](https://ext.dcloud.net.cn),有各种玲琅满目的组件、模板。
其中成套的全端兼容ui库包括:
- [uViewUI](www.uviewui.com):整合了非常多组件,功能丰富、文档清晰,但不支持nvue
- [colorUI css库](http://ext.dcloud.net.cn/plugin?id=239):颜值很高,css库而非组件
- [unify UI](https://ext.dcloud.net.cn/plugin?id=2251):全端支持的组件库,侧重nvue
- [mypUI](https://ext.dcloud.net.cn/plugin?id=2190):全端支持的组件库,侧重nvue
- [ThorUI组件库](https://ext.dcloud.net.cn/plugin?id=556)
- [graceUI商业库](http://grace.hcoder.net/)
### 其他
- 如果你仍坚持使用微信小程序的自定义组件ui,插件市场也有很多vant weapp版的集成示例[https://ext.dcloud.net.cn/search?q=vant](https://ext.dcloud.net.cn/search?q=vant)。同时要注意,小程序自定义组件的性能不如vue组件。
- 如果你的nvue文件使用weex编译模式,也支持weex ui。三方商业ui库有graceUI weex版。但weex编译模式属于被淘汰技术,不再提供技术支持,nvue开发请使用uni-app编译模式。
综上,官方对组件的使用建议是:
1. 首先使用内置组件
2. 然后使用uni ui扩展组件
3. 其他需求依靠插件市场其他组件灵活补充
\ No newline at end of file
......@@ -18,7 +18,7 @@
|App |H5 |微信小程序 |支付宝小程序|百度小程序 |字节跳动小程序、飞书小程序|QQ小程序 |快应用 |360小程序|快手小程序 |
|:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |
|2.0+,app-vue|2.4.5+ |基础库 2.7.0+|x |需引入动态库[引入方式](/api/media/editor-context) |x |x |x |x |x |
|2.0+,app-vue|2.4.5+ |基础库 2.7.0+|x |需引入动态库[引入方式](https://smartprogram.baidu.com/docs/develop/framework/dynamiclib_use/) |x |x |x |x |x |
editor组件目前只有H5、App的vue页面、微信小程序、百度小程序支持,其他端平台自身未提供editor组件,只能使用web-view加载web页面,也可搜索[插件市场](https://ext.dcloud.net.cn/search?q=%E5%AF%8C%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91) 获取简单的markdown富文本编辑器
......
......@@ -10,7 +10,7 @@
**Tips**
* 由于 icon 组件各端表现存在差异,可以通过使用 [字体图标](/frame?id=字体图标) 的方式来弥补各端差异。
* 由于 icon 组件各端表现存在差异,可以通过使用 [字体图标](/tutorial/syntax-css.html#字体图标) 的方式来弥补各端差异。
**属性说明**
......
......@@ -128,7 +128,7 @@ App平台软键盘弹出有 adjustResize|adjustPan 两种模式,默认为 adju
- adjustResize模式在Android App上,弹起键盘和收回键盘时,因为要重设webview窗体高度,可能会在个别安卓机型闪现灰屏或漏出下层页面内容。
- 小程序端在 input 聚焦期间,避免使用 css 动画。
- H5平台只能在用户交互时修改 focus 生效。
- 如果遇到 focus 属性设置不生效的问题参考:[组件属性设置不生效解决办法](/vue-api?id=_4-组件属性设置不生效解决办法)
- 如果遇到 focus 属性设置不生效的问题参考:[组件属性设置不生效解决办法](/tutorial/vue-api.html#componentsolutions)
- 如需禁止点击其他位置收起键盘的默认行为,可以监听`touch`事件并使用`prevent`修饰符(仅支持App、H5,其他平台可以通过设置`focus`来使输入框重新获取焦点),例如在确认按钮上使用:```@touchend.prevent="onTap"```
......
......@@ -74,7 +74,7 @@ headerHeight|吸顶距离|Number|是|子list吸顶距离最外层滚动容器顶
`scrollToElement(ref, options)`
滚动到指定位置,详情 [https://uniapp.dcloud.net.cn/nvue-api?id=scrolltoelement](https://uniapp.dcloud.net.cn/nvue-api?id=scrolltoelement)
滚动到指定位置,详情 [scrollToElement](https://uniapp.dcloud.net.cn/tutorial/nvue-api.html#dom)
#### 事件
......
......@@ -122,10 +122,10 @@
使用流程如下:
[MapContext.initMarkerCluster](api/location/map?id=createmapcontext) 对聚合点进行初始化配置(可选);
[MapContext.addMarkers](api/location/map?id=createmapcontext) 指定参与聚合的 marker;
MapContext.on('markerClusterCreate', callback) 触发时,通过 [MapContext.addMarkers](api/location/map?id=createmapcontext) 更新聚合簇的样式 (可选);
[MapContext.removeMarkers](api/location/map?id=createmapcontext) 移除参与聚合的 marker;
[MapContext.initMarkerCluster](/api/location/map?id=createmapcontext) 对聚合点进行初始化配置(可选);
[MapContext.addMarkers](/api/location/map?id=createmapcontext) 指定参与聚合的 marker;
MapContext.on('markerClusterCreate', callback) 触发时,通过 [MapContext.addMarkers](/api/location/map?id=createmapcontext) 更新聚合簇的样式 (可选);
[MapContext.removeMarkers](/api/location/map?id=createmapcontext) 移除参与聚合的 marker;
**polyline**
......@@ -237,7 +237,7 @@ export default {
}
```
map 组件相关操作的 JS API:[uni.createMapContext](api/location/map?id=createmapcontext)
map 组件相关操作的 JS API:[uni.createMapContext](/api/location/map?id=createmapcontext)
nvue map 更换箭头图标格式参考: [https://ask.dcloud.net.cn/article/37901](https://ask.dcloud.net.cn/article/37901)
**注意事项**
......
......@@ -10,7 +10,7 @@
当然也可以不拖动,而使用代码来触发`movable-view``movable-area`里的移动缩放。
`movable-view`的规范另见[下文](/component/movable-view?id=movable-view)
`movable-view`的规范另见[下文](#movable-view)
**平台差异说明**
......@@ -75,7 +75,7 @@
**Tips**
- movable-view必须在`<movable-area/>`组件中,并且必须是直接子节点,否则不能移动。
- 如果遇到x、y、scale属性设置不生效的问题参考:[组件属性设置不生效解决办法](/vue-api?id=componentsolutions)
- 如果遇到x、y、scale属性设置不生效的问题参考:[组件属性设置不生效解决办法](/tutorial/vue-api.html#componentsolutions)
- 除了H5端和app-nvue端,其他平台不支持内嵌video、map等原生组件。更新:微信基础库2.4.4起支持了原生组件在 scroll-view、swiper、movable-view 中的使用
**示例**[查看演示](https://hellouniapp.dcloud.net.cn/pages/component/movable-view/movable-view)
......
......@@ -13,7 +13,7 @@
|url|String||应用内的跳转链接,值为相对路径或绝对路径,如:"../first/first","/pages/first/first",注意不能加 ``.vue`` 后缀||
|open-type|String|navigate|跳转方式||
|delta|Number||当 open-type 为 'navigateBack' 时有效,表示回退的层数||
|animation-type|String|pop-in/out|当 open-type 为 navigate、navigateBack 时有效,窗口的显示/关闭动画效果,详见:[窗口动画](api/router?id=animation)|App|
|animation-type|String|pop-in/out|当 open-type 为 navigate、navigateBack 时有效,窗口的显示/关闭动画效果,详见:[窗口动画](/api/router?id=animation)|App|
|animation-duration|Number|300|当 open-type 为 navigate、navigateBack 时有效,窗口显示/关闭动画的持续时间。|App|
|hover-class|String|navigator-hover|指定点击时的样式类,当hover-class="none"时,没有点击态效果||
|hover-stop-propagation|Boolean|false|指定是否阻止本节点的祖先节点出现点击态|微信小程序|
......@@ -73,7 +73,7 @@ export default {
}
```
url有长度限制,太长的字符串会传递失败,可使用[窗体通信](https://uniapp.dcloud.io/collocation/frame/communication)[全局变量](https://ask.dcloud.net.cn/article/35021),或`encodeURIComponent`等多种方式解决,如下为`encodeURIComponent`示例。
url有长度限制,太长的字符串会传递失败,可使用[窗体通信](https://uniapp.dcloud.io/tutorial/page.html#emit)[全局变量](https://ask.dcloud.net.cn/article/35021),或`encodeURIComponent`等多种方式解决,如下为`encodeURIComponent`示例。
```html
<navigator :url="'/pages/navigate/navigate?item='+ encodeURIComponent(JSON.stringify(item))"></navigator>
```
......
......@@ -45,7 +45,7 @@
|disabled|Boolean|false|是否禁用(快手小程序不支持)|
**bug & tips**
- 由于 JavaScript 的限制 vue 不能观测如下方式设置 value:``this.value[0] = 0``[vue 注意事项](https://cn.vuejs.org/v2/guide/list.html#注意事项)),解决方式参考:[hello-uniapp 示例](https://github.com/dcloudio/hello-uniapp/commit/59264474172a591c865431d02a2a1e3583978827)
- 由于 JavaScript 的限制 vue 不能观测如下方式设置 value:``this.value[0] = 0``[vue 注意事项](/tutorial/vue-basics.html#listrendering)),解决方式参考:[hello-uniapp 示例](https://github.com/dcloudio/hello-uniapp/commit/59264474172a591c865431d02a2a1e3583978827)
- 微信开发工具的pc模拟器有可能出现拖动数据错乱,使用真机正常
#### 时间选择器
......
......@@ -36,7 +36,7 @@ key|可选属性,用于指定列表数据中可以作为唯一标识的键值
`<recycle-list>` 添加 switch 属性可以用来指定数据中用于区分子模板类型的字段名,语义和编程语言里的 switch 一致,配合 `<cell-slot>` 中的 case 和 default 属性一起使用。
如果省略了 switch 属性,则只会将第一个 `<cell-slot>` 视为模板,多余的模板将会被忽略。
```
```html
<recycle-list for="(item, i) in longList" switch="type">
<cell-slot case="A">
<text>- A {{i}} -</text>
......@@ -55,7 +55,7 @@ key|可选属性,用于指定列表数据中可以作为唯一标识的键值
`<recycle-list>` 中使用的子组件也将被视为模板,在开发组件时给 `<template>` 标签添加 recyclable 属性,才可以用在 `<recycle-list>` 中。
```
```html
<template recyclable>
<div>
<text>...</text>
......@@ -74,7 +74,7 @@ key|可选属性,用于指定列表数据中可以作为唯一标识的键值
例如,下列写法不可用:
```
```html
<div :prop="capitalize(card.title)">
<text>{{ card.title | capitalize }}</text>
</div>
......@@ -111,7 +111,7 @@ key|可选属性,用于指定列表数据中可以作为唯一标识的键值
组件的属性 目前子组件的属性不支持函数。(正在讨论实现方案)
```
```html
<sub-component :prop="item.xxx" />
```
......@@ -129,7 +129,7 @@ key|可选属性,用于指定列表数据中可以作为唯一标识的键值
计划支持。`vm.$on`, `vm.$once`, `vm.$emit`, `vm.$off` 等功能还未完全调通,接口可用,但是行为可能有些差异(参数丢失),暂时不要使用。
#### 示例
```
```html
<recycle-list for="(item, i) in longList" switch="type">
<cell-slot case="A">
<text>- A {{i}} -</text>
......@@ -141,7 +141,7 @@ key|可选属性,用于指定列表数据中可以作为唯一标识的键值
```
如果有如下数据:
```
```js
const longList = [
{ type: 'A' },
{ type: 'B' },
......@@ -153,7 +153,7 @@ const longList = [
则会生成如下等价节点:
```
```html
<text>- A 0 -</text>
<text>- B 1 -</text>
<text>- B 2 -</text>
......@@ -163,7 +163,7 @@ const longList = [
如果将模板合并成一个,也可以省略 `switch``case`,将例子进一步简化:
```
```html
<recycle-list for="(item, i) in longList">
<cell-slot>
<text>- {{item.type}} {{i}} -</text>
......
......@@ -171,5 +171,5 @@ export default {
- scroll-into-view 的优先级高于 scroll-top。
- scroll-view是区域滚动,不会触发页面滚动,无法触发pages.json配置的下拉刷新、页面触底onReachBottomDistance、titleNView的transparent透明渐变。
- 若要使用下拉刷新,建议使用页面的滚动,而不是 scroll-view 。插件市场有前端模拟的基于scroll-view的下拉刷新,但性能不佳。如必需使用前端下拉刷新,推荐使用基于wxs的下拉刷新,性能会比基于js监听方式更高。
- 如果遇到scroll-top、scroll-left、refresher-triggered属性设置不生效的问题参考:[组件属性设置不生效解决办法](/vue-api?id=componentsolutions)
- 如果遇到scroll-top、scroll-left、refresher-triggered属性设置不生效的问题参考:[组件属性设置不生效解决办法](/tutorial/vue-api?id=componentsolutions)
- scroll-view的滚动条设置,可通过css的-webkit-scrollbar自定义,包括隐藏滚动条。(app-nvue无此css)
......@@ -51,7 +51,7 @@ change 事件返回 detail 中包含一个 source 字段,表示导致变更的
- 如果 nvue 页面 ``@animationfinish`` 事件不能返回正确的数据,可同时监听 ``@change`` 事件。
- 使用竖向滚动时,需要给 ``<scroll-view>`` 一个固定高度,通过 css 设置 height。
- 注意:其中只可放置 ``<swiper-item>`` 组件,否则会导致未定义的行为。
- 如果遇到current、current-item-id属性设置不生效的问题参考:[组件属性设置不生效解决办法](/vue-api?id=_4-组件属性设置不生效解决办法)
- 如果遇到current、current-item-id属性设置不生效的问题参考:[组件属性设置不生效解决办法](/tutorial/vue-api.html#componentsolutions)
- banner图的切换效果和指示器的样式,有多种风格可自定义,可在[uni-app插件市场](https://ext.dcloud.net.cn/search?q=%E8%BD%AE%E6%92%AD)搜索
- 如需banner管理后台,参考uniCloud admin banner插件:[https://ext.dcloud.net.cn/plugin?id=4117](https://ext.dcloud.net.cn/plugin?id=4117)
- swiper在App的vue中、百度支付宝头条QQ小程序中,不支持内嵌video、map等原生组件。在微信基础库2.4.4起和App nvue2.1.5起支持内嵌原生组件。竖向的swiper内嵌视频可实现抖音、映客等视频垂直拖动切换效果。
......
......@@ -82,18 +82,18 @@ export default {
**Tips**
- textarea 的 blur 事件会晚于页面上的 tap 事件,如果需要在 button 的点击事件获取 textarea,可以使用 form 的 @submit。
- 如果遇到 value 属性设置不生效的问题参考:[组件属性设置不生效解决办法](/vue-api?id=_4-组件属性设置不生效解决办法)
- 如果遇到 value 属性设置不生效的问题参考:[组件属性设置不生效解决办法](/tutorial/vue-api.html#componentsolutions)
- 微信小程序、百度小程序、字节跳动小程序、飞书小程序中,textarea是原生组件,层级高于前端组件,请勿在 scroll-view、swiper、picker-view、movable-view 中使用 textarea 组件。覆盖textarea需要使用cover-view。[详见](/component/native-component)
- 小程序端 css 动画对 textarea 组件无效。
- H5 平台只能在用户交互时修改 focus 生效。
- 如果遇到 focus 属性设置不生效的问题参考:[组件属性设置不生效解决办法](/vue-api?id=_4-组件属性设置不生效解决办法)
- 如果遇到 focus 属性设置不生效的问题参考:[组件属性设置不生效解决办法](/tutorial/vue-api.html#componentsolutions)
- 软键盘的弹出和收起逻辑,详见[input的文档](/component/input?id=app%E5%B9%B3%E5%8F%B0ios%E7%AB%AF%E8%BD%AF%E9%94%AE%E7%9B%98%E4%B8%8A%E6%96%B9%E6%A8%AA%E6%9D%A1%E5%8E%BB%E9%99%A4%E6%96%B9%E6%A1%88)
- 如需禁止点击其他位置收起键盘的默认行为,可以监听`touch`事件并使用`prevent`修饰符(仅支持App、H5,其他平台可以通过设置`focus`来使输入框重新获取焦点),例如在确认按钮上使用:```@touchend.prevent="onTap"```
- js中给textarea组件赋值为字符串,在字符串中加\n可实现换行。
- nvue 样式 `word-wrap` 在 Android 平台暂不支持
- 旧版本chrome或同内核浏览器会将输入多个标点符号放在一行,此时可通过将textarea样式设置为`word-break: break-word;`实现自动换行。
```
```html
<template>
<view class="content">
<textarea class="textarea" v-model="txt"></textarea>
......@@ -113,7 +113,7 @@ export default {
nvue下键盘右下角按钮点击仅触发换行;如想监听该按钮事件可以参考,示例代码如下:
```
```html
<template>
<view class="content">
<textarea class="textarea" v-model="txt"></textarea>
......
......@@ -6,7 +6,7 @@
它类似于传统html中的div,用于包裹各种元素内容。
如果使用[nvue](https://uniapp.dcloud.io/nvue-outline),则需注意,包裹文字应该使用`<text>`组件。
如果使用[nvue](https://uniapp.dcloud.io/tutorial/nvue-outline),则需注意,包裹文字应该使用`<text>`组件。
**属性说明**
......
此差异已折叠。
......@@ -13,7 +13,7 @@
**uni-app和原生小程序混合开发问题:**
- 方式1:把原生小程序转换为uni-app源码。有各种转换工具,[详见](translate.md)
- 方式2:新建一个uni-app项目,把原生小程序的代码变成小程序组件,进而整合到uni-app项目下。uni-app支持使用小程序wxml组件,[参考](frame.md?id=小程序组件支持)
- 方式2:新建一个uni-app项目,把原生小程序的代码变成小程序组件,进而整合到uni-app项目下。uni-app支持使用小程序wxml组件,[参考](/tutorial/miniprogram-subject.html#小程序自定义组件支持)
- 方式3:原生开发的小程序仍保留,部分新功能使用uni-app开发。
* 使用发行为混合分包的功能
+ 在 HBuilderX 3.1.0+ 中点击发行小程序的菜单,勾选发行混合分包,填写分包目录名称,打包后,将对应目录文件拷贝至已有小程序中,需要自己补充原小程序app.json中的页面或分包配置
......
......@@ -39,12 +39,12 @@ H5没有原生组件概念问题,非H5端有原生组件并引发了原生组
如果你的代码没有直接使用这些,那很可能是引入的三方库使用了这些。如果是后者,去[插件市场](https://ext.dcloud.net.cn/)搜索替代方案。要知道非H5端的js是运行在一个独立的js core或v8下,并不是运行在浏览器里。
从HBuilderX 2.6起,App端新增了renderjs,这是一种运行在视图层的js,vue页面通过renderjs可以操作浏览器对象,进而可以让基于浏览器的库直接在uni-app的App端运行,诸如echart、threejs,详见:[https://uniapp.dcloud.io/frame?id=renderjs](https://uniapp.dcloud.io/frame?id=renderjs)
从HBuilderX 2.6起,App端新增了renderjs,这是一种运行在视图层的js,vue页面通过renderjs可以操作浏览器对象,进而可以让基于浏览器的库直接在uni-app的App端运行,诸如echart、threejs,详见:[renderjs](https://uniapp.dcloud.io/tutorial/renderjs)
3. 使用了非H5端不支持的vue语法,受小程序自定义组件限制的写法,[详见](/vue-components)
4. 不要在引用组件的地方在组件属性上直接写 style="xx",要在组件内部写样式
5. `url(//alicdn.net)`等路径,改为`url(https://alicdn.net)`,因为在App端//是file协议
6. 很多人在H5端联网时使用本地测试服务地址(localhost或127.0.0.1),这样的联网地址手机App端是无法访问的,请使用手机可访问的IP进行联网
1. 使用了非H5端不支持的vue语法,受小程序自定义组件限制的写法,[详见](/tutorial/vue-components)
2. 不要在引用组件的地方在组件属性上直接写 style="xx",要在组件内部写样式
3. `url(//alicdn.net)`等路径,改为`url(https://alicdn.net)`,因为在App端//是file协议
4. 很多人在H5端联网时使用本地测试服务地址(localhost或127.0.0.1),这样的联网地址手机App端是无法访问的,请使用手机可访问的IP进行联网
### H5正常但小程序异常的可能性
1. 同上
......@@ -114,7 +114,7 @@ vue页面在App端的渲染引擎默认是系统webview(不是手机自带浏
- 出于降低h5应用向uni-app迁移成本的考虑,写成div、span也可以运行在app和小程序上,因为uni-app编译器会把这些HTML标签编译为小程序标签。但仍然建议养成新习惯。
3. Css注意
- 虽然大部分css样式在微信小程序和app中都可以支持,但推荐使用flex布局模型,这种布局更灵活高效且支持更多平台(比如nvue、快应用只支持flex布局)
- 单位方面,uni-app默认为rpx。这是一种可跨端的通用单位 [详见](/frame?id=%E5%B0%BA%E5%AF%B8%E5%8D%95%E4%BD%8D)
- 单位方面,uni-app默认为rpx。这是一种可跨端的通用单位 [详见](/tutorial/syntax-css#尺寸单位)
4. 工程目录注意
- 每个要显示的页面,都要放到pages目录下,新建一个页面所在的目录,然后放同名目录的vue文件,比如project/pages/lista/lista.vue,并且在pages.json里配置。这与小程序的策略相同。
- 自定义组件,放到component目录
......@@ -192,7 +192,7 @@ vue页面在App端的渲染引擎默认是系统webview(不是手机自带浏
2.自定义组件渲染差异
微信(可以使用[virtualHost](https://uniapp.dcloud.io/vue-api?id=%e5%85%b6%e4%bb%96%e9%85%8d%e7%bd%ae)配置)/QQ/百度/字节跳动这四家小程序,自定义组件在渲染时会比App/H5端多一级节点,在写样式时需要注意:
微信(可以使用[virtualHost](https://uniapp.dcloud.io/tutorial/vue-api.html#其他配置)配置)/QQ/百度/字节跳动这四家小程序,自定义组件在渲染时会比App/H5端多一级节点,在写样式时需要注意:
* 使用`flex`布局时,直接给自定义组件的父元素设置为`display:flex`不能影响到自定义组件内部的根节点,需要设置当前自定义组件为`display:flex`才可以。
* 在自定义组件内部设置根元素高度为100%,不能撑满自定义组件父元素。需要同时设置当前自定义组件高度为100%才可以。
......
## 介绍
```uni-app``` App端内置了一个基于 weex 改进的原生渲染引擎,提供了原生渲染能力。
在App端,如果使用vue页面,则使用webview渲染;如果使用nvue页面(native vue的缩写),则使用原生渲染。一个App中可以同时使用两种页面,比如首页使用nvue,二级页使用vue页面,hello uni-app示例就是如此。
虽然nvue也可以多端编译,输出H5和小程序,但nvue的css写法受限,所以如果你不开发App,那么不需要使用nvue。
以往的 weex ,有个很大的问题是它只是一个高性能的渲染器,没有足够的API能力(比如各种push sdk集成、蓝牙等能力调用),使得开发时非常依赖原生工程师协作,开发者本来想节约成本,结果需要前端、iOS、Android 3拨人开发,适得其反。 nvue 解决了这个问题,让前端工程师可以直接开发完整 App,并提供丰富的插件生态和云打包。这些组合方案,帮助开发者切实的提高效率、降低成本。
同时```uni-app```扩展了weex原生渲染引擎的很多排版能力,修复了很多bug。比如
- Android端良好支持边框阴影,[详情](/nvue-css?id=android-box-shadow)
- iOS端支持高斯模糊,<a href="https://ask.dcloud.net.cn/article/36617#view" target="_blank">详情</a>
- 可实现区域滚动长列表+左右拖动列表+吸顶的复杂排版效果
- 优化圆角边框绘制性能
- 扩展了更多的css
## 适用场景
nvue的组件和API写法与vue页面一致,其内置组件还比vue页面内置组件增加了更多,[详见](https://uniapp.dcloud.io/component/list)。
如果你熟悉 weex或react native 开发,那么 nvue 是你的更优选择,能切实提升你的开发效率,降低成本。
如果你是web前端,不熟悉原生排版,那么建议你仍然以使用vue页面为主,在App端某些vue页面表现不佳的场景下使用 nvue 作为强化补充。这些场景如下:
1. 需要高性能的区域长列表或瀑布流滚动。webview的页面级长列表滚动是没有性能问题的(就是滚动条覆盖webview整体高度),但页面中某个区域做长列表滚动,则需要使用nvue的```list```、```recycle-list```、```waterfall```等组件([详见](https://uniapp.dcloud.io/component/list))。这些组件的性能要高于vue页面里的区域滚动组件```scroll-view```。
2. 复杂高性能的自定义下拉刷新。uni-app的pages.json里可以配置原生下拉刷新,但引擎内置的下拉刷新样式只有雪花和circle圈2种样式。如果你需要自己做复杂的下拉刷新,推荐使用nvue的refresh组件。当然[插件市场](https://ext.dcloud.net.cn/search?q=%E4%B8%8B%E6%8B%89%E5%88%B7%E6%96%B0)里也有很多vue下的自定义下拉刷新插件,只要是基于renderjs或wxs的,性能也可以商用,只是没有nvue的```refresh```组件更极致。
3. 左右拖动的长列表。在webview里,通过```swiper```+```scroll-view```实现左右拖动的长列表,前端模拟下拉刷新,这套方案的性能不好。此时推荐使用nvue,比如新建uni-app项目时的[新闻示例模板](https://ext.dcloud.net.cn/plugin?id=103),就采用了nvue,切换很流畅。
4. 实现区域滚动长列表+左右拖动列表+吸顶的复杂排版效果,效果可参考hello uni-app模板里的```swiper-list```。[详见](https://ext.dcloud.net.cn/plugin?id=2128)
5. 如需要将软键盘右下角按钮文字改为“发送”,则需要使用nvue。比如聊天场景,除了软键盘右下角的按钮文字处理外,还涉及聊天记录区域长列表滚动,适合nvue来做。
6. 解决前端控件无法覆盖原生控件的层级问题。当你使用```map```、```video```、```live-pusher```等原生组件时,会发现前端写的```view```等组件无法覆盖原生组件,层级问题处理比较麻烦,此时使用nvue更好。或者在vue页面上也可以覆盖一个subnvue(一种非全屏的nvue页面覆盖在webview上),以解决App上的原生控件层级问题。[详见](https://uniapp.dcloud.io/component/native-component)
7. 如深度使用```map```组件,建议使用nvue。除了层级问题,App端nvue文件的map功能更完善,和小程序拉齐度更高,多端一致性更好。
8. 如深度使用```video```,建议使用nvue。比如如下2个场景:video内嵌到swiper中,以实现抖音式视频滑动切换,例子见[插件市场](https://ext.dcloud.net.cn/search?q=%E4%BB%BF%E6%8A%96%E9%9F%B3);nvue的视频全屏后,通过```cover-view```实现内容覆盖,比如增加文字标题、分享按钮。
9. 直播推流:nvue下有```live-pusher```组件,和小程序对齐,功能更完善,也没有层级问题。
10. 对App启动速度要求极致化。App端如果首页使用nvue且在manifest里配置fast模式,那么App的启动速度可以控制在1秒左右。而使用vue页面的话,App的启动速度一般是3秒起,取决于你的代码性能和体积。
但注意,在某些场景下,nvue不如vue页面,如下:
1. ```canvas```。nvue的canvas性能不高,尤其是Android App平台,所以这个组件干脆没有内置,而是需要单独引入。操作canvas动画,最高性能的方式是使用vue页面的renderjs技术,在hello uni-app里的canvas示例就是如此。
2. 动态横竖屏。nvue页面的css不支持媒体查询,所以横竖屏动态切换、动态适配屏幕是很困难的。
## 纯原生渲染模式
uni-app在App端,支持vue页面和nvue页面混搭、互相跳转。也支持纯nvue原生渲染。
启用纯原生渲染模式,可以减少App端的包体积、减少使用时的内存占用。因为webview渲染模式的相关模块将被移除。
在manifest.json源码视图的```"app-plus"```下配置```"renderer":"native"```,即代表App端启用纯原生渲染模式。此时pages.json注册的vue页面将被忽略,vue组件也将被原生渲染引擎来渲染。
如果不指定该值,默认是不启动纯原生渲染的。
```javascript
// manifest.json
{
// ...
// App平台特有配置
"app-plus": {
"renderer": "native", //App端纯原生渲染模式
}
}
```
## 编译模式
**weex编译模式和uni-app编译模式**
如你之前是weex开发者,可以继续查阅本章节,否则可以跳过看下一节[快速上手](#快速上手)。
weex的组件和JS API,与uni-app不同。uni-app与微信小程序相同。
考虑到weex用户的迁移,uni-app 也支持weex的代码写法。在manifest.json中可以配置使用**weex编译模式**或**uni-app编译模式**。选择weex编译模式时将不支持uni-app的组件和jsapi,需要开发者参考weex官方文档的写法来写代码。 比如 weex 编译模式用```<div>```。uni-app 编译模式则使用```<view>```。
一般情况建议使用```uni-app```模式,除非历史weex代码较多,需要逐步过渡。同时注意weex编译模式的切换是项目级的,不支持同项目下某个nvue页面使用weex模式,另一个nvue页面使用uni-app模式。
| |weex编译模式 |uni-app编译模式 |
|-- |-- |-- |
|平台 |仅App |所有端,包含小程序和H5 |
|组件 |weex组件如div |uni-app组件如view |
|生命周期 |只支持weex生命周期 |支持所有uni-app生命周期 |
|JS API |weex API、uni API、Plus API |weex API、uni API、Plus API |
|单位 |750px是屏幕宽度,wx是固定像素单位 |750rpx是屏幕宽度,px是固定像素单位|
|全局样式 |手动引入 |app.vue的样式即为全局样式 |
|页面滚动 |必须给页面套或组件 |默认支持页面滚动 |
在 manifest.json 中修改2种编译模式,```manifest.json``` -> ```app-plus``` -> ```nvueCompiler``` 切换编译模式。
```nvueCompiler``` 有两个值:
- weex
- uni-app
```javascript
// manifest.json
{
// ...
// App平台特有配置
"app-plus": {
"nvueCompiler":"uni-app" //是否启用 uni-app 模式
}
}
```
在 `manifest.json` 配置文件中,HBuilderX2.4之前版本,默认值为 `weex` 模式,HBuilderX2.4+版本默认值改为 `uni-app` 模式。
weex 编译模式不支持 ```onNavigationBarButtonTap``` 生命周期函数的写法。在 nvue 中监听原生标题栏按钮点击事件,详见:[uni.onNavigationBarButtonTap](https://uniapp.dcloud.net.cn/frame?id=%e9%a1%b5%e9%9d%a2%e7%94%9f%e5%91%bd%e5%91%a8%e6%9c%9f)。
weex编译模式不支持onShow生命周期,但熟悉5+的话,可利用监听webview的```addEventListener``` show事件实现onShow效果。
weex 编译模式不支持`vuex`。
nvue 的页面跳转,与 weex 不同,仍然遵循 uni-app 的路由模型。vue 页面和 nvue 页面之间不管怎么跳转,都遵循这个模型。包括 nvue 页面跳向 nvue 页面。每个页面都需要在 pages.json 中注册,调用 uni-app 的 [路由 API](https://uniapp.dcloud.net.cn/api/router) 进行跳转。
原生开发没有页面滚动的概念,页面内容高过屏幕高度时,内容并不会自动滚动;只有将页面内容放在`list`、`waterfall`、`scroll-view/scroller`这几个组件下内容才可滚动。这不符合前端开发的习惯,所以在 nvue 编译为 `uni-app`模式时,`uni-app`框架会给nvue页面外层自动嵌套一个 `scroller`,从而实现页面内容的自动滚动。
注意:
- `uni-app`框架仅对nvue页面嵌套`scroller`容器,不会给组件自动套`scroller`容器;
- 若nvue页面有`recycle-list`组件时,`uni-app`框架也不会自动给页面嵌套`scroller`容器
- 若你不希望自动嵌套`scroller`容器,可在`pages.json`中通过如下配置进行关闭:
```javascript
{
"path": "",
"style": {
"disableScroll": true // 不嵌套 scroller
}
}
```
weex 编译模式下支持使用 weex ui ,例子[详见](https://ext.dcloud.net.cn/plugin?id=442)。但相比uni-app插件市场及官方[uni ui](https://ext.dcloud.net.cn/plugin?id=55)而言,weex语法的组件生态还是比较欠缺的。
**HBuilderX 3.1.0+ 开始支持新的样式编译模式**
- weex 编译模式:老模式,样式支持与普通 weex 相同
- uni-app 编译模式:新模式,在 weex 原有样式基础上支持组合选择器(相邻兄弟选择器、普通兄弟选择器、子选择器、后代选择器)[详见](https://ask.dcloud.net.cn/article/38751)
```js
// manifest.json
{
// ...
// App平台特有配置
"app-plus": {
"nvueStyleCompiler": "uni-app"
}
}
```
## 快速上手
### 1.新建nvue页面
在HBuilderX的 ```uni-app``` 项目中,新建页面,弹出界面右上角可以选择是建立```vue```页面还是```nvue```页面,或者2个同时建。
不管是vue页面还是nvue页面,都需要在```pages.json```中注册。如果在HBuilderX中新建页面是会自动注册的,如果使用其他编辑器,则需要自行在pages.json里注册。
如果一个页面路由下同时有vue页面和nvue页面,即出现同名的vue和nvue文件。那么在App端,会仅使用nvue页面,同名的vue文件将不会被编译到App端。而在非App端,会优先使用vue页面。
如果不同名,只有nvue页面,则在非app端,只有uni-app编译模式的nvue文件才会编译。
### 2.开发nvue页面
```nvue``` 页面结构同 ```vue```, 由 ```template```、```style```、```script``` 构成。
- template: 模板写法、数据绑定同 vue。组件支持2种模式,
- weex 组件,同weex写法,参考:[weex 内置组件](http://emas.weex.io/zh/docs/components/a.html);
- uni-app组件,同uni-app写法。
- App端nvue专用组件,详见[https://uniapp.dcloud.io/component/barcode](https://uniapp.dcloud.io/component/barcode)。
- style:由于采用原生渲染,**并非所有浏览器的 css 均支持,布局模型只支持 flex 布局**,虽然不会造成某些界面布局无法实现,但写法要注意。详见:[样式](/nvue-css)
- script:写法同 vue,并支持3种API:
- nvue API :仅支持App端,uni-app编译模式也可使用。使用前需先引入对应模块,参考:[模块引入API](/nvue-api)
- uni API:[https://uniapp.dcloud.io/api/README](https://uniapp.dcloud.io/api/README)
- plus API:仅支持App端。[http://www.html5plus.org/doc/h5p.html](http://www.html5plus.org/doc/h5p.html)
### 3.调试 nvue 页面
HBuilderX内置了weex调试工具的强化版,包括审查界面元素、看log、debug打断点,[详见](https://uniapp.dcloud.io/snippet?id=%e5%85%b3%e4%ba%8e-app-%e7%9a%84%e8%b0%83%e8%af%95)
## render-whole
在HBuilder X 3.1.0起版本,nvue 新增 `render-whole`属性,类型`Boolean`。
- 设置render-whole="true"时,视图层将组件以及子组件的信息结构一次性和原生层通讯,通过整个节点的重绘提升了排版渲染性能。
- 设置render-whole="false"时,视图层将以子节点一个接着一个和原生层通讯再重绘。总体的渲染时间可能更久。
默认启用`render-whole`为`true`的组件列表
- `text`
- `cell`
- `header`
- `cell-slot`
- `recycle-list`
**使用**
```html
<swiper :render-whole="true"></swiper>
```
**演示**
> 此演示在Android 5.1版本手机上的效果,高版本手机效果没有这么明显
<img style="width:300px;" src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/29c0c580-55ab-11eb-a16f-5b3e54966275.gif"></img>
示例工程[点击下载](https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/d5adb160-55af-11eb-bd01-97bc1429a9ff.zip)
## nvue开发与vue开发的常见区别
基于原生引擎的渲染,虽然还是前端技术栈,但和web开发肯定是有区别的。
1. nvue 页面控制显隐只可以使用```v-if```不可以使用```v-show```
2. nvue 页面只能使用``` flex ```布局,不支持其他布局方式。页面开发前,首先想清楚这个页面的纵向内容有什么,哪些是要滚动的,然后每个纵向内容的横轴排布有什么,按 flex 布局设计好界面。
3. nvue 页面的布局排列方向默认为竖排(```column```),如需改变布局方向,可以在 ```manifest.json``` -> ```app-plus``` -> ```nvue``` -> ```flex-direction``` 节点下修改,仅在 uni-app 模式下生效。[详情](https://uniapp.dcloud.io/collocation/manifest?id=nvue)。
4. nvue页面编译为H5、小程序时,会做一件css默认值对齐的工作。因为weex渲染引擎只支持flex,并且默认flex方向是垂直。而H5和小程序端,使用web渲染,默认不是flex,并且设置```display:flex```后,它的flex方向默认是水平而不是垂直的。所以nvue编译为H5、小程序时,会自动把页面默认布局设为flex、方向为垂直。当然开发者手动设置后会覆盖默认设置。
5. 文字内容,必须、只能在```<text>```组件下。不能在```<div>```、```<view>```的```text```区域里直接写文字。否则即使渲染了,也无法绑定js里的变量。
6. 只有```text```标签可以设置字体大小,字体颜色。
7. 布局不能使用百分比、没有媒体查询。
8. nvue 切换横竖屏时可能导致样式出现问题,建议有 nvue 的页面锁定手机方向。
9. 支持的css有限,不过并不影响布局出你需要的界面,```flex```还是非常强大的。详见
10. 不支持背景图。但可以使用```image```组件和层级来实现类似web中的背景效果。因为原生开发本身也没有web这种背景图概念
11. css选择器支持的比较少,只能使用 class 选择器。[详见](/nvue-css)
12. nvue 的各组件在安卓端默认是透明的,如果不设置```background-color```,可能会导致出现重影的问题。
13. ```class``` 进行绑定时只支持数组语法。
14. Android端在一个页面内使用大量圆角边框会造成性能问题,尤其是多个角的样式还不一样的话更耗费性能。应避免这类使用。
15. nvue页面没有```bounce```回弹效果,只有几个列表组件有```bounce```效果,包括 ```list```、```recycle-list```、```waterfall```。
16. 原生开发没有页面滚动的概念,页面内容高过屏幕高度并不会自动滚动,只有部分组件可滚动(```list```、```waterfall```、```scroll-view/scroller```),要滚得内容需要套在可滚动组件下。这不符合前端开发的习惯,所以在 nvue 编译为 uni-app模式时,给页面外层自动套了一个 ```scroller```,页面内容过高会自动滚动。(组件不会套,页面有```recycle-list```时也不会套)。后续会提供配置,可以设置不自动套。
17. 在 App.vue 中定义的全局js变量不会在 nvue 页面生效。```globalData```和```vuex```是生效的。
18. App.vue 中定义的全局css,对nvue和vue页面同时生效。如果全局css中有些css在nvue下不支持,编译时控制台会报警,建议把这些不支持的css包裹在[条件编译](https://uniapp.dcloud.io/platform)里,```APP-PLUS-NVUE```
19. 不能在 ```style``` 中引入字体文件,nvue 中字体图标的使用参考:[加载自定义字体](/nvue-api?id=addrule)。如果是本地字体,可以用```plus.io```的API转换路径。
20. 目前不支持在 nvue 页面使用 ```typescript/ts```。
21. nvue 页面关闭原生导航栏时,想要模拟状态栏,可以[参考文章](https://ask.dcloud.net.cn/article/35111)。但是,仍然强烈建议在nvue页面使用原生导航栏。nvue的渲染速度再快,也没有原生导航栏快。原生排版引擎解析```json```绘制原生导航栏耗时很少,而解析nvue的js绘制整个页面的耗时要大的多,尤其在新页面进入动画期间,对于复杂页面,没有原生导航栏会在动画期间产生整个屏幕的白屏或闪屏。
## iOS平台下拉组件refresh组件注意问题
iOS平台默认情况下滚动容器组件(如```list```、```waterfall```组件)内容不足时,由于没有撑满容器的可视区域会导致无法上下滚动,此时无法操作下拉刷新功能,无法触发```refresh```组件的```@refresh```、```@pullingdown```事件。 此时可在容器组件中配置```alwaysScrollableVertical```属性值为```true```来设置支持上下滚动,支持下拉刷新操作。
##### 用法
```html
<list class="scroll-v list" enableBackToTop="true" scroll-y alwaysScrollableVertical="true">
<refresh class="refresh" @refresh="onrefresh()" @pullingdown="onpullingdown">
<!-- refresh content -->
</refresh>
<cell v-for="(newsitem,index) in list" :key="newsitem.id">
<!-- cell content -->
</cell>
</list>
```
> Android平台不存在此问题
### 插件全景图
\ No newline at end of file
* [插件全景图](/plugin/README.md)
* [插件市场介绍](/plugin/plugin-ext-introduction.md)
* [uni_modules](/plugin/uni_modules.md)
* [原生插件](/plugin/native-plugin.md)
* [插件作者专区](/plugin/plugin-author.md)
\ No newline at end of file
### 插件作者专区
[oauth开放平台](https://open.dcloud.net.cn/pages/login/login)
\ No newline at end of file
### 插件市场介绍
\ No newline at end of file
......@@ -123,7 +123,7 @@ HBuilderX 2.7.10+ 版支持
* dev 和 build 模式的区别:
1. dev 模式有 SourceMap 可以方便的进行断点调试;
2. build 模式会将代码进行压缩,体积更小更适合发布为正式版应用;
3. 进行 [环境判断](/frame?id=运行环境判断) 时,dev 模式 process.env.NODE_ENV 的值为 development,build 模式 process.env.NODE_ENV 的值为 production。
3. 进行 [环境判断](/worktile/running-env?id=判断平台) 时,dev 模式 process.env.NODE_ENV 的值为 development,build 模式 process.env.NODE_ENV 的值为 production。
## 使用cli创建项目和使用HBuilderX可视化界面创建项目有什么区别
......@@ -143,4 +143,4 @@ HBuilderX 2.7.10+ 版支持
*`cli` 使用有疑问,欢迎扫码加入 uni-app 微信交流群讨论:
<br/><img src="https://img.cdn.aliyun.dcloud.net.cn/guide/uniapp/wx-barcode.png" width="250"/>
注意:HBuilderX创建的项目,一样可以使用npm,参考:[https://uniapp.dcloud.io/frame?id=npm%e6%94%af%e6%8c%81](https://uniapp.dcloud.io/frame?id=npm%e6%94%af%e6%8c%81)
注意:HBuilderX创建的项目,一样可以使用npm,参考:[NPM 支持](/tutorial/page-script?id=npm支持)
> `uni-app`支持通过 可视化界面、[`vue-cli`命令行](https://uniapp.dcloud.io/quickstart?id=%e9%80%9a%e8%bf%87vue-cli%e5%91%bd%e4%bb%a4%e8%a1%8c) 两种方式快速创建项目。
> `uni-app`支持通过 可视化界面、[`vue-cli`命令行](https://uniapp.dcloud.io/tutorial/quickstart-cli) 两种方式快速创建项目。
可视化的方式比较简单,HBuilderX内置相关环境,开箱即用,无需配置nodejs。
......@@ -111,7 +111,7 @@ HBuilderX 还提供了快捷运行菜单,可以按数字快速选择要运行
<img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/aef21b70-4f37-11eb-a16f-5b3e54966275.png"/>
</div>
如需调试,可参考:[uni-app调试](/snippet?id=使用-chrome-调试)
如需调试,可参考:[uni-app调试](/tutorial/snippet?id=使用-chrome-调试)
## 发布uni-app
......
> `uni-app`支持通过 可视化界面、[`vue-cli`命令行](https://uniapp.dcloud.io/quickstart?id=%e9%80%9a%e8%bf%87vue-cli%e5%91%bd%e4%bb%a4%e8%a1%8c) 两种方式快速创建项目。
> `uni-app`支持通过 可视化界面、[`vue-cli`命令行](https://uniapp.dcloud.io/tutorial/quickstart?id=%e9%80%9a%e8%bf%87vue-cli%e5%91%bd%e4%bb%a4%e8%a1%8c) 两种方式快速创建项目。
### 1. 通过 HBuilderX 可视化界面
......
......@@ -111,7 +111,7 @@
+ 小程序平台 修复 百度小程序 login 组件 @getphonenumber 无参数的问题 [详情](https://ask.dcloud.net.cn/question/130022)
* 【uniCloud】
+ 新增 批量短信 发送功能 [详情](https://uniapp.dcloud.net.cn/uniCloud/send-sms)
+ 新增 uniCloud DB Schema 支持国际化 [详情](https://uniapp.dcloud.net.cn/collocation/i18n?id=schema)
+ 新增 uniCloud DB Schema 支持国际化 [详情](https://uniapp.dcloud.net.cn/worktile/i18n?id=schema)
+ 新增 腾讯云redis
* 【App插件(含5+App和uni-app的App端)】
+ 新增 拍照和本地相册选择 crop 裁剪编辑图片支持 saveToAlbum 属性设置是否保存编辑后的图片到相册 [文档](https://www.html5plus.org/doc/zh_cn/camera.html#plus.camera.CameraCropStyles)
......@@ -301,10 +301,10 @@
* 【uniCloud】
+ 【重要】clientDB 新增 支持使用 getTemp 对主表、副表过滤后再联表查询,大幅提升联表查询性能 [详情](https://uniapp.dcloud.net.cn/uniCloud/clientdb?id=lookup-with-temp)
#### 3.2.5.20210827-alpha
#### 3.2.5.20210827-alpha
* 【uni-app】
+ 【重要】新增 uni-app Vue3 版本 支持运行和发行到 App
+ 新增 uni-app Vue3 版本 发行到H5 支持以SSR方式发行 [详情](https://uniapp.dcloud.io/collocation/ssr)
+ 【重要】新增 uni-app Vue3 版本 支持运行和发行到 App
+ 新增 uni-app Vue3 版本 发行到H5 支持以SSR方式发行 [详情](https://uniapp.dcloud.io/tutorial/ssr)
+ App平台、H5平台 新增 uni.getLocale、uni.setLocale 接口,用于获取和设置应用语言 [详情](https://uniapp.dcloud.io/api/ui/locale)
+ App平台、H5平台 修复 scroll-view 组件滚动过快时 scroll 事件回调返回信息不正确的Bug [详情](https://ask.dcloud.net.cn/question/128573)
+ App平台、H5平台 修复 canvas 组件 createPattern 方法无效的Bug [详情](https://ask.dcloud.net.cn/question/128793)
......@@ -793,13 +793,13 @@
#### 3.1.5.20210316-alpha
* 【uni-app】
+ App平台、H5平台 优化 uni.showModal、uni.showActionSheet 等 API 内置国际化支持 [详情](https://uniapp.dcloud.io/collocation/i18n)
+ App平台 优化 应用退出提示内置国际化支持 [详情](https://uniapp.dcloud.io/collocation/i18n)
+ App平台 优化 uni.scanCode、uni.previewImage 等 API 内置国际化支持 [详情](https://uniapp.dcloud.io/collocation/i18n)
+ App平台、H5平台 优化 uni.showModal、uni.showActionSheet 等 API 内置国际化支持 [详情](https://uniapp.dcloud.io/worktile/i18n)
+ App平台 优化 应用退出提示内置国际化支持 [详情](https://uniapp.dcloud.io/worktile/i18n)
+ App平台 优化 uni.scanCode、uni.previewImage 等 API 内置国际化支持 [详情](https://uniapp.dcloud.io/worktile/i18n)
+ App平台 修复 SelectorQuery.exec 在安卓 4.x 系统报错的 Bug
+ App-iOS平台 修复 nvue ad-draw 组件播放优量汇视频广告可能无声音的Bug
+ App-iOS平台 修复 subNVue input 组件获取焦点后隐藏页面时软键盘不会关闭的Bug [详情](https://ask.dcloud.net.cn/question/117872)
+ H5平台 优化 picker、video 组件内置国际化支持 [详情](https://uniapp.dcloud.io/collocation/i18n)
+ H5平台 优化 picker、video 组件内置国际化支持 [详情](https://uniapp.dcloud.io/worktile/i18n)
* 【uniCloud】
+ unicloud-db组件 add、update、remove方法新增可选参数needConfirm、needLoading、loadingTitle [详情](https://uniapp.dcloud.net.cn/uniCloud/unicloud-db?id=add)
+ unicloud-db组件 新增 load 事件支持 pagination [详情](https://uniapp.dcloud.net.cn/uniCloud/unicloud-db?id=loadevent)
......@@ -861,7 +861,7 @@
#### 3.1.1.20210204-alpha
* 【uni-app】
+ 【重要】App平台 新增 nvue 组件支持 render-whole 属性。可以按组件整体渲染,而不是从上到下逐行渲染 [详情](https://uniapp.dcloud.io/nvue-outline?id=render-whole)
+ 【重要】App平台 新增 nvue 组件支持 render-whole 属性。可以按组件整体渲染,而不是从上到下逐行渲染 [详情](https://uniapp.dcloud.io/tutorial/nvue-outline?id=render-whole)
+ App平台 新增 manifest.json 支持 nvue css 编译新旧版本配置 app-plus -> nvueStyleCompiler。可切换老版的nvue css 编译器 [详情](https://ask.dcloud.net.cn/article/38751)
+ App平台 修复 纯 nvue 编译模式下 pages.json 缺少 style 节点编译报错的Bug
+ App平台 修复 3.1.0 版本引出的 nvue 页面中样式与 app.vue 样式冲突的Bug [详情](https://ask.dcloud.net.cn/question/116787)
......@@ -1687,7 +1687,7 @@
#### 2.7.11.20200602-alpha
* 【uni-app】
+ 【重要】支持运行和发布到 华为快应用 [详情](https://uniapp.dcloud.io/matter?id=quickapp-webview-huawei)
+ 【重要】支持运行和发布到 华为快应用 [详情](https://uniapp.dcloud.io/tutorial/matter?id=quickapp-webview-huawei)
+ App平台 修复 使用小程序组件时局部组件不显示的Bug
+ App平台 修复 canvasContext.fillText 部分设备多次调用失败的Bug [详情](https://ask.dcloud.net.cn/question/97609)
+ App平台 修复 canvasContext.drawImage 无法绘制 base64 格式图像的Bug [详情](https://ask.dcloud.net.cn/question/95050)
......@@ -1735,7 +1735,7 @@
#### 2.7.6.20200521-alpha
* 【uni-app】
+ 【重要】支持运行和发布到 360小程序 [详情](https://uniapp.dcloud.io/matter?id=mp-360)
+ 【重要】支持运行和发布到 360小程序 [详情](https://uniapp.dcloud.io/tutorial/matter?id=mp-360)
+ App平台 修复 class 名称中含有 rpx、upx 时不生效的Bug [详情](https://ask.dcloud.net.cn/question/96981)
+ App-Android平台 修复 HBuilderX2.7.0 引出的 uni.hideTabBar 隐藏 tabbar 后页面高度可能不正确的Bug [详情](https://ask.dcloud.net.cn/question/96244)
+ App-Android平台 修复 nvue textarea 组件获取焦点后在部分手机可能会被软键盘遮挡的Bug [详情](https://ask.dcloud.net.cn/question/96914)
......@@ -2048,7 +2048,7 @@
#### 2.6.6.20200320-alpha
* 【uni-app】
+ 优化 静态资源引入方式 [详情](https://uniapp.dcloud.io/frame?id=resource)
+ 优化 静态资源引入方式 [详情](https://uniapp.dcloud.io/tutorial/page-static-assets)
+ 修复 内联 wxs 里包含“!”符号时报错的Bug [详情](https://ask.dcloud.net.cn/question/90581)
+ 修复 TypeScript 项目部分情况(存在 easycom 组件),内置组件报未注册的Bug [#1400](https://github.com/dcloudio/uni-app/issues/1400)
+ 修复 uni.scss 内条件编译失效的Bug [详情](https://ask.dcloud.net.cn/question/90454)
......
建议第一步,看完[uni-app官网](https://uniapp.dcloud.io)的首页介绍。
建议第二步,通过[快速上手](https://uniapp.dcloud.io/quickstart),亲身体验下uni-app。
建议第二步,通过[快速上手](https://uniapp.dcloud.io/quickstart-hx),亲身体验下uni-app。
建议第三步,看完[《uni-app官方教程》](https://ke.qq.com/course/3169971),出品人:DCloud,课时:共3节。
[a]({{ $themeConfig.domainName }})
#### 如果你熟悉h5,但不熟悉vue和小程序
1. 看完这篇[白话uni-app](http://ask.dcloud.net.cn/article/35657)
2. DCloud与vue合作,在[vue.js官网](https://cn.vuejs.org/v2/guide/)提供了免费视频教程,也可以直达教程地址:[https://learning.dcloud.io](https://learning.dcloud.io)
......
......@@ -23,7 +23,7 @@ DCloud的盈利方式在帮助开发者进行流量变现(uni-AD)和提供
应用开发中,90%的常规开发,比如界面组件、联网等api,```uni-app```封装为可跨多端的API。
而各个端的特色功能,```uni-app```引入[条件编译](http://uniapp.dcloud.io/platform)。可以优雅的在一个项目里调用不同平台的特色能力。比如push,微信小程序里不支持,但可以在App里使用,还有很多原生sdk,在App时难免涉及,这些都可以正常的在```uni-app```框架下使用。
而各个端的特色功能,```uni-app```引入[条件编译](http://uniapp.dcloud.io/tutorial/platform)。可以优雅的在一个项目里调用不同平台的特色能力。比如push,微信小程序里不支持,但可以在App里使用,还有很多原生sdk,在App时难免涉及,这些都可以正常的在```uni-app```框架下使用。
下图是```uni-app```产品功能框架图,```uni-app```在保持uni规范跨平台的前提下,还可实现每个平台特有的平台能力(如微信小程序平台,可继续调用微信卡劵等微信特有业务API)。
......@@ -108,8 +108,8 @@ uni-app提供了大量的扩展api解决了这个问题,并且发展了成熟
```uni-app``` 积极拥抱社区现有的现代开发流程,包括但不限于:
- 内置了webpack
- NPM 包管理系统,详见[参考](http://uniapp.dcloud.io/frame?id=npm%E6%94%AF%E6%8C%81)
- es6+ 语法(发布时会自动编译为es5),详见[参考](http://uniapp.dcloud.io/frame?id=es6-%E6%94%AF%E6%8C%81)
- NPM 包管理系统,详见[参考](http://uniapp.dcloud.io/tutorial/page-script#npm支持)
- es6+ 语法(发布时会自动编译为es5),详见[参考](http://uniapp.dcloud.io/tutorial/syntax-js#es6-支持)
- 各种预处理器(less、scss、stylus、typescript)
- uni-app的官方ide:HBuilderX,在vue、json、markdown、代码提示、操作效率上,有非常明显的优势,可帮助开发者大幅提高工作效率
- uni-app同时也提供了cli方式,可使用其他开发工具如vscode开发,当然开发效率不如HBuilderX。对比详见[https://ask.dcloud.net.cn/article/35451](https://ask.dcloud.net.cn/article/35451)
......@@ -121,9 +121,9 @@ uni-app提供了大量的扩展api解决了这个问题,并且发展了成熟
- 丰富的插件市场为开发者提供数千款现成的轮子,[https://ext.dcloud.net.cn](https://ext.dcloud.net.cn)
- 兼容微信小程序 JS SDK,丰富的小程序生态内容可直接引入uni-app,并且在App侧通用,[参考](http://ask.dcloud.net.cn/article/35070)
- 兼容微信小程序自定义组件,并且App、H5侧通用,[参考](http://uniapp.dcloud.io/frame?id=小程序组件支持)
- App和H5提供了renderjs,使得浏览器专用的库也可以在App和H5里使用,[参考](https://uniapp.dcloud.io/frame?id=renderjs)
- 支持 NPM 包管理系统,[参考](http://uniapp.dcloud.io/frame?id=npm%E6%94%AF%E6%8C%81)
- 兼容微信小程序自定义组件,并且App、H5侧通用,[参考](http://uniapp.dcloud.io/tutorial/miniprogram-subject#小程序自定义组件支持)
- App和H5提供了renderjs,使得浏览器专用的库也可以在App和H5里使用,[参考](https://uniapp.dcloud.io/tutorial/renderjs)
- 支持 NPM 包管理系统,[参考](http://uniapp.dcloud.io/tutorial/page-script#npm支持)
- 支持 mpvue 项目及组件,[参考](http://ask.dcloud.net.cn/article/34945)
- 支持原生插件,见插件市场:[https://ext.dcloud.net.cn](https://ext.dcloud.net.cn)
- 支持App原生工程里嵌入uni小程序sdk。
......
#### 跨域
\ No newline at end of file
## 开发规范
为了实现多端兼容,综合考虑编译速度、运行性能等因素,```uni-app``` 约定了如下开发规范:
- 页面文件遵循 [Vue 单文件组件 (SFC) 规范](https://vue-loader.vuejs.org/zh/spec.html)
- 组件标签靠近小程序规范,详见[uni-app 组件规范](component/README.md)
- 接口能力(JS API)靠近微信小程序规范,但需将前缀 ```wx``` 替换为 ```uni```,详见[uni-app接口规范](api/README.md)
- 数据绑定及事件处理同 ```Vue.js``` 规范,同时补充了App及页面的生命周期
- 为兼容多端运行,建议使用flex布局进行开发
\ No newline at end of file
此差异已折叠。
#### App 打包
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册