Le développement Web mobile peut utiliser vue. Vue est un framework JavaScript open source capable de développer des applications d'une seule page ; il peut être utilisé comme framework d'application Web et est conçu pour simplifier le développement Web. Vue prend en charge le développement mobile et convient à la création d'applications Web mobiles ; son coût d'entrée est faible et sa mise en route est rapide. Il peut être développé en conjonction avec des bibliothèques d'interface utilisateur frontales matures telles que i-view et Element UI.
L'environnement d'exploitation de ce tutoriel : système windows7, version vue3, ordinateur DELL G3.
Vue.js est un framework JavaScript open source capable de développer des applications monopage. Il peut également être utilisé comme cadre d'application Web et est conçu pour simplifier le développement Web. Le développement d'applications Vue.js a attiré beaucoup d'attention de la part des développeurs du monde entier pour créer de superbes applications Web.
Vue.js est populaire pour de nombreuses raisons, l'une des principales raisons étant sa capacité à effectuer un nouveau rendu sans aucune action. Il vous permet de créer des composants réutilisables, petits mais puissants. Il fournit donc un cadre composable qui vous permet d'ajouter des composants en cas de besoin.
vue.js prend en charge le développement mobile et convient à la création d'applications Web mobiles. Pour le terminal mobile, vue est le premier choix ; il a un faible coût d'entrée et est rapide à démarrer. Il peut être développé en conjonction avec certaines bibliothèques d'interface utilisateur frontales matures telles que i-view et Element UI.
L'application est très simple. Inutile de dire qu'elle utilise vuejs. La gestion du module de développement de composants utilise vue-loader et le changement de page et les animations cinématiques utilisent vue-router. à la tendance des données de l'application. De plus, il peut être utilisé avec Diverses bibliothèques d'interface utilisateur pour rendre les applications plus belles. Vous pouvez utiliser SUI ou Framework7, une branche de Framework7, qui est souvent utilisée (car jQuery peut être utilisé dans des fonctionnalités ultérieures. ajouts. [Recommandations associées : Tutoriel d'introduction à vuejs]
Adaptation du terminal mobile
Par rapport au terminal PC, les résolutions des terminaux mobiles sont de toutes sortes étranges. et étrange. Pour tout développeur, l'adaptation du terminal mobile est la clé du développement de notre terminal mobile. Le premier problème à rencontrer lors du développement
Du côté du mobile, on peut souvent voir ce code dans la balise head :
<meta name='viewport' content='width=device-width,initial-scale=1,user-scale=no' />
Le paramétrage. de la fenêtre d'affichage via la balise méta définit le taux de zoom de la page ; vous devez d'abord comprendre ces paramètres. Nous devons d'abord connaître la signification de plusieurs largeurs de fenêtre d'affichage
layoutviewport
La largeur de mise en page est la. largeur de la page Weblayoutviewport
布局宽度,就是网页的宽度visualviewport
可是宽度,就是浏览器窗口的宽度,这个值决定了我们手机一屏能看到的内容;visualviewport
和layoutviewport
的大小关系,决定了是否会出现滚动条,当visualviewport
更大或者刚好等于layoutviewport
时是不会出现滚动条的。idealviewport
为浏览器定义的可完美适配移动端的viewport,固定不变,可以认为是设备视口宽度device-width
。meta的设置其实就是对layoutviewport
和visualviewport
进行设置。
width=device-width
表示页面宽度layoutviewport
与设备视口宽度idealviewport
一致initial-scale=1
表示页面宽度和网页宽度与设备视口宽度的初始缩放比例,visualviewport
由这个比例决定,但是对于layoutviewport
来说,它同时受到两个属性的影响,然后取其中较大的那个值。user-scale=no
禁止缩放所以现在我们知道,这段在移动端常见的代码的意思,即将visualviewport
和layoutviewport
设置为idealviewport
visualviewport
Mais la largeur est la fenêtre du navigateur. La largeur de Visualviewport est plus grande ou juste égale à layoutviewport
, les barres de défilement le feront. n'apparaît pas. idealviewport
est une fenêtre définie par le navigateur qui peut parfaitement s'adapter au terminal mobile. Elle est fixe et peut être considérée comme la largeur de la fenêtre d'affichage de l'appareil device-width</code. >. Le paramètre de <p><span style="font-size: 14px;"><strong>meta définit en fait le <code>layoutviewport
et le visualviewport
width=device-width
. la largeur de la page layoutviewport
est cohérente avec la largeur de la fenêtre d'affichage de l'appareil idealviewport
initial-scale= 1
représente le rapport de mise à l'échelle initial de la largeur de la page et de la page Web la largeur par rapport à la largeur de la fenêtre d'affichage de l'appareil. visualviewport
est déterminé par ce rapport, mais pour layoutviewport
, il est également affecté par l'influence de deux attributs, puis prend la valeur la plus grande. user-scale=no
Désactiver la mise à l'échelleNous connaissons donc maintenant la signification de ce code commun sur les terminaux mobiles, à savoir visualviewport
et layoutviewport< /code > est défini sur la valeur de <code>idealviewport
; de cette façon, nous n'aurons pas de barres de défilement sur le terminal mobile et le contenu Web pourra être mieux affiché. Dans ce principe, nous envisagerons l'adaptation de. la page.
Lorsque les images de l'interface utilisateur sont dessinées, elles ont généralement une largeur fixe, mais les largeurs de nos appareils mobiles réels sont cependant différentes, si le rapport de mise à l'échelle des éléments de la page est cohérent avec le rapport de mise à l'échelle de la largeur de la page, dans différentes tailles. L'effet de notre page Web sera également cohérent sous l'appareil.
🎜 Utiliser des unités relatives 🎜🎜🎜🎜🎜🎜rem🎜🎜🎜🎜rem est relatif à la taille de la police de l'élément racine html pour le calcul. Ceci est généralement réalisé en définissant document.documentElement.style.fontSize lorsque la page est initialisée et chargée. Généralement, nous définissons la taille de la police de l'élément racine HTML à 1/10 de la largeur. La largeur des différents appareils est différente, mais le rapport rem de la même valeur est cohérent avec le rapport de largeur de l'appareil. 🎜document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
视口单位
将视口宽度window.innerWidth
和视口高度window.innerHeight
(即layoutviewport
)等分为 100 份。
vw : 1vw 为视口宽度的 1% vh : 1vh 为视口高度的 1% vmin : vw 和 vh 中的较小值 vmax : 选取 vw 和 vh 中的较大值
和rem相比较,视口单位不需要使用js对根元素进行设置,兼容性稍差,但是大部分设备都已经支持了,同样的无须再开发时进行单位换算,直接使用相关的插件postcss-px-to-viewport在输出的时候进行转换。
修改viewport
之前我们提到了layoutviewport
布局宽度实际上不是一个固定值,而是通过meta设置属性,通过idealviewport
计算出来的值,我们可以通过控制meta的属性来将layoutviewport
固定为某一个值。一般设计图的宽度为750px,现在我们的目标就是将layoutviewport
设置为750px;layoutviewport
受到两个属性的影响,width属性我们之间设置为750,initial-scale缩放比例应该为idealviewport
的宽度/750;当我们未改变meta标签属性的时候,layoutviewport
的值其实就是idealviewport
的值,所以可以通过document.body.clientWidth
或者window.innerWidth
来获取。
;(function () { const width = document.body.clientWidth || window.innerWidth const scale = width / 750 const content = 'width=750, initial-scale=' + scale + ', minimum-scale=' + scale + ', maximum-scale=' + scale + ', viewport-fit=cover' document.querySelector('meta[name="viewport"]').content = content })()
设置完成之后,layoutviewport
在不同的设备中会始终保持为750px,我们开发时可以直接使用设计稿尺寸。
布局样式
布局的方式可以是各种各样的,但是出于兼容性的考虑,有些样式我们最好避免使用,难以解决的问题,那就不去面对。
需要谨慎对待的fixed
position:fixed
在日常的页面布局中非常常用,在许多布局中起到了关键的作用。它的作用是:position:fixed
的元素将相对于屏幕视口(viewport)的位置来指定其位置。并且元素的位置在屏幕滚动时不会改变。
但是,在许多特定的场合,position:fixed
的表现与我们想象的大相径庭。
iOS弹出键盘;软键盘唤起后,页面的 fixed元素将失效(iOS认为用户更希望的是元素随着滚动而移动,也就是变成了 absolute 定位),既然变成了absolute,所以当页面超过一屏且滚动时,失效的 fixed 元素就会跟随滚动了。
当元素祖先的 transform 属性非 none 时,定位容器由视口改为该祖先。说的简单点,就是position:fixed
的元素会相对于最近的并且应用了transform的祖先元素定位,而不是窗口。导致这个现象的原因是使用了transform的元素将创建一个新的堆叠上下文。堆叠上下文(Stacking Context):堆叠上下文是 HTML 元素的三维概念,这些 HTML 元素在一条假想的相对于面向(电脑屏幕的)视窗或者网页的用户的 z 轴上延伸,HTML 元素依据其自身属性按照优先级顺序占用层叠上下文的空间。顺序如下图所示,总之堆叠上下文会对定位关系产生影响。想要进一步可以查看不受控制的 position:fixed。
键盘弹出与使用transform属性的情况在移动端是很常见的,所以需要谨慎使用position:fixed
。
推荐使用flex
flex,即弹性布局,移动端兼容性较好,能够满足大部分布局需求。现在我们使用flex来实现h5中常见的顶部标题栏+中部滚动内容+底部导航栏的布局;实现效果如下:
首先我们来实现整体的布局,整体布局应该是一个方向为flex-direction: column;
并且占据整个窗口的弹性盒子,然后里面的布局,应该是首尾为固定高度,中间内容区域为flex: 1;
。
html, body { padding: 0; margin: 0; } .page { position: absolute; top: 0; bottom: 0; width: 100%; display: flex; flex-direction: column; .page-content { flex: 1; overflow-y: auto; } }
然后再来实现底部标题栏,底部标题栏一般由居中标题和左右操作区域组成;为了实现中间区域标题居中,我们左右两部分应该保持相同的宽度。
<template> <div> <div> 左 </div> <div> <slot>Title</slot> </div> <div> <div>右</div> </div> </div> </template> <script> export default { name: 'HeadBar' } </script> <style scoped> .header { display: flex; width: 100%; line-height: 88px; height: 88px; font-size: 36px; background-color: #42b983; z-index: 999; color: #fff; transition: background-color .5s ease; .header__main { flex: 1; display: flex; justify-content: center; align-items: center; text-align: center; } .header__left, .header__right { padding: 0 16px; width: 120px; } .header__left { text-align: left; } .header__right { text-align: right; } } </style>
底部导航栏主体部分,其实是单个导航选项平分导航栏;而每个导航选项,是一个方向为flex-direction: column;
布局方式横向为align-items: center;
,竖向为justify-content: space-around;
<template> <div> <div> <div></div> <span>选项1</span> </div> <div> <div></div> <span>选项2</span> </div> <div> <div></div> <span>选项3</span> </div> <div> <div></div> <span>选项4</span> </div> </div> </template> <script> export default { name: 'BottomTaber', data () { return { } } } </script> <style scoped> .taber { background-color: #42b983; color: #fff; height: 88px; display: flex; .taber-item { flex: 1; display: flex; flex-direction: column; justify-content: space-around; align-items: center; } .icon { width: 36px; height: 36px; background-color: #fff; } } </style>
页面跳转
转场动画
在vue中我们通过vue-router来管理路由,每个路由跳转类似与在不同的页面之间进行切换,从用户友好的角度来说,每次切换页面的时候最好添加一个转场效果。如果转场动画不区分路由是打开新页面、还是返回之前页面我们只需要在<router-view>
外使用<transition>
添加一个动画效果即可;但是一般打开和返回是应用不同的动画效果的,所以我们需要在切换路由的时候区分路由是前进还是后退。为了区分路由的动作,我们在路由文件中设置meta为数字,meta表示其路由的深度,然后监听$route,根据to、from meta值的大小设置不同的跳转动画。如果应用到多种跳转动画,可以根据详情,具体情况具体应用。
<template> <transition :name="transitionName"> <router-view></router-view> </transition> </template> <script> export default { name: 'app', data () { return { transitionName: 'fade' } }, watch: { '$route' (to, from) { let toDepth = to.meta let fromDepth = from.meta if (fromDepth > toDepth) { this.transitionName = 'fade-left' } else if (fromDepth < toDepth) { this.transitionName = 'fade-right' } else { this.transitionName = 'fade' } } } } </script>
虽然这样能够实现跳转效果,但是需要在编写router时添加设置,比较麻烦;我们可以使用开源项目vue-navigation
来实现,更加方便,无须对router进行多余的设置。npm i -S vue-navigation
安装,在main.js中导入:
import Navigation from 'vue-navigation' Vue.use(Navigation, {router}) // router为路由文件
在App.vue中设置:
this.$navigation.on('forward', (to, from) => { this.transitionName = 'fade-right' }) this.$navigation.on('back', (to, from) => { this.transitionName = 'fade-left' }) this.$navigation.on('replace', (to, from) => { this.transitionName = 'fade' })
vue-navigation插件还有一个重要的功能就是保存页面状态,与keep-alive相似,但是keep-alive保存状态无法识别路由的前进后退,而实际应用中,我们的需求是返回页面时,希望页面状态保存,当进入页面时希望获取新的数据,使用vue-navigation可以很好的实现这个效果。具体使用可以查看vue-navigation有详细使用说明与案例。另外也可以尝试vue-page-stack,两个项目都能实现我们需要的效果,vue-page-stack
借鉴了vue-navigation
,也实现了更多的功能,并且最近也一直在更新。
PS: 这里的动画效果引用自animate.scss;
底部导航栏
之前我们已经实现了底部导航栏的基本样式,这里我们再做一些说明。当页面路由路径与router-link
的路由匹配时,router-link
将会被设置为激活状态,我们可以通过设置active-class
来设置路径激活时应用的类名,默认为router-link-active
,而激活的类名还有一个router-link-exact-active
,这个类名是由exact-active-class
来设置的,同样是设置路径激活时应用的类名;active-class
与exact-active-class
其实是由路由的匹配方式决定的。
一般路由的匹配方式是包含匹配。 举个例子,如果当前的路径是 /a 开头的,那么 也会被设置 CSS 类名。按照这个规则,每个路由都会激活 ,而使用exact
属性可以使用“精确匹配模式”。精确匹配只有当路由完全相同的时候才会被激活。
路由守卫
移动端的路由守卫一般不会太复杂,主要是登录权限的判断,我们设置一个路由白名单,将所有不需要登录权限的路由放入其中;对于需要登录的路由做判断,没有登录就跳转登录页面,要求用户进行登录后在访问,如果登录后需要返回原有路由就把目标页面的路由作为参数传递给登录页面,再在登录后进行判断,如果存在目标页面参数就跳转目标页面,没有就跳转首页。
如果你的应用涉及到权限,那需要标注每个路由需要的权限,在meta中设置roles,roles是数组来保存需要的权限;从后台的接口中获取用户拥有的权限和roles进行对比就可以判断是否具有相关权限了。
const whiteList = ['/login'] router.beforeEach((to, from, next) => { const hasToken = store.getters.auth if (hasToken) { if (to.path === '/login') { next({ path: '/' }) } else { const needRoles = to.meta && to.meta.roles && to.meta.roles.length > 0 if (needRoles) { const hasRoles = store.state.user.roles.some(role => to.meta.roles.includes(role)) if (hasRoles) { next() } else { next('/403') } } else { next() } } } else { if (whiteList.includes(to.path)) { next() } else { next('/login') } } })
组件
自动加载
在我们的项目中,往往会使用的许多组件,一般使用频率比较高的组件为了避免重复导入的繁琐一般是作为全局组件在项目中使用的。而注册全局组件我们首先需要引入组件,然后使用Vue.component
进行注册;这是一个重复的工作,我们每次创建组件都会进行,如果我们的项目是使用webpack构建(vue-cli也是使用webpack),我们就可以通过require.context
自动将组件注册到全局。创建components/index.js
文件:
export default function registerComponent (Vue) { /** * 参数说明: * 1. 其组件目录的相对路径 * 2. 是否查询其子目录 * 3. 匹配基础组件文件名的正则表达式 **/ const modules = require.context('./', false, /\w+.vue$/) modules.keys().forEach(fileName => { // 获取组件配置 const component = modules(fileName) // 获取组件名称,去除文件名开头的 `./` 和结尾的扩展名 const name = fileName.replace(/^\.\/(.*)\.\w+$/, '$1') // 注册全局组件 // 如果这个组件选项是通过 `export default` 导出的, // 那么就会优先使用 `.default`, // 否则回退到使用模块的根。 Vue.component(name, component.default || component) }) }
之后在main.js
中导入注册模块进行注册,使用require.context
我们也可以实现vue插件和全局filter的导入。
import registerComponent from './components' registerComponent(Vue)
通过v-model绑定数据
v-model
是语法糖,它的本质是对组件事件进行监听和数据进行更新,是props和$on监听事件的缩写,v-model
默认传递value
,监听input
事件。现在我们使用v-model
来实现下数字输入框,这个输入框只能输入数字,在组件中我们只需要定义value来接受传值,然后在输入值满足我们输入条件(输入为数字)的时候使用$emit
触发input
事件。
<template> <div> <input type="text" :value="value" @input="onInput"> </div> </template> <script> export default { name: 'NumberInput', props: { value: String }, methods: { onInput (event) { if (/^\d+$/.test(event.target.value)) { this.$emit('input', event.target.value) } else { event.target.value = this.value } } } } </script>
使用的时候,我们只需要使用v-model
绑定值就可以了。v-model
默认会利用名为value
的prop
和名为input
的事件,但是很多时候我们想使用不同的prop
和监听不同的事件,我们可以使用model
选项进行修改。
Vue.component('my-checkbox', { model: { prop: 'checked', event: 'change' }, props: { // this allows using the `value` prop for a different purpose value: String, // use `checked` as the prop which take the place of `value` checked: { type: Number, default: 0 } }, // ... })
<my-checkbox v-model="foo" value="some value"></my-checkbox>
上述代码相当于:
<my-checkbox :checked="foo" @change="val => { foo = val }" value="some value"> </my-checkbox>
通过插件的方式来使用组件
在很多第三方组件库中,我们经常看到直接使用插件的方式调用组件的方式,比如VantUI的Dialog弹出框组件,我们不但可以使用组件的方式进行使用,也可以通过插件的形式进行调用。
this.$dialog.alert({ message: '弹窗内容' });
将组件作为插件使用的原理其实并不复杂,就是使用手动挂载Vue组件实例。
import Vue from 'vue'; export default function create(Component, props) { // 先创建实例 const vm = new Vue({ render(h) { // h就是createElement,它返回VNode return h(Component, {props}) } }).$mount(); // 手动挂载 document.body.appendChild(vm.$el); // 销毁方法 const comp = vm.$children[0]; comp.remove = function() { document.body.removeChild(vm.$el); vm.$destroy(); } return comp; }
调用create
传入组件和props
参数就可以获取组件的实例,通过组件实例我们就可以调用组件的各种功能了。
<template> <div v-show="visible"> 加载中 </div> </template> <script> export default { name: 'Loading', data () { return { visible: false } }, methods: { show () { this.visible = true }, hide () { this.visible = false } } } </script> <style scoped> .loading-wrapper { position: absolute; top: 0; bottom: 0; width: 100%; background-color: rgba(0, 0, 0, .4); z-index: 999; } </style> <!--使用--> const loading = create(Loading, {}) loading.show() // 显示 loading.hide() // 关闭
第三方组件
移动端各种组件、插件已经相对完善,在项目开发中重复造轮子是一件很不明智的事情;开发项目时我们可以借助第三方组件、插件提高我们的开发效率。
常用组件库
VantUI是有赞开源的一套轻量、可靠的移动端Vue组件库;支持按需引入、主题定制、SSR,除了常用组件外,针对电商场景还有专门的业务组件,如果是开发电商项目的话,推荐使用。官方文档关于主题定制是在webpack.config.js
中进行设置的:
// webpack.config.js module.exports = { rules: [ { test: /\.less$/, use: [ // ...其他 loader 配置 { loader: 'less-loader', options: { modifyVars: { // 直接覆盖变量 'text-color': '#111', 'border-color': '#eee' // 或者可以通过 less 文件覆盖(文件路径为绝对路径) 'hack': `true; @import "your-less-file-path.less";` } } } ] } ] };
但我们的项目可能是使用vue-cli构建,这时我们需要在vue.config.js
中进行设置:
module.exports = { css: { loaderOptions: { less: { modifyVars: { 'hack': `true; @import "~@/assets/less/vars.less";` } } } } }
常用插件
better-scroll是一个为移动端各种滚动场景提供丝滑的滚动效果的插件,如果在vue中使用可以参考作者的文章当 better-scroll 遇见 Vue。
swiper是一个轮播图插件,如果是在vue中使用可以直接使用vue-awesome-swiper,vue-awesome-swiper
基于Swiper4
,并且支持SSR。
【Recommandations associées : tutoriel vidéo vuejs, développement web front-end】
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!