vue全家桶学习

416 阅读4分钟

vue起步

Vue.js 是什么

一套用于构建用户界面的渐进式框架(主张少,没有多做职责之外的事,在开发过程中来按需引入功能,不是一次性都放进来的,有点类似于迭代开发。)与其他框架不同的是,vue被设计成自底向上逐层应用,vue的核心库只关心视图层,易上手也便于与第三方库或既有项目整合 当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

声明式渲染

数据和 DOM 已经被建立了关联,所有东西都是响应式的

条件与循环

不仅可以把数据绑定到 DOM 文本或 attribute,还可以绑定到 DOM 结构

处理用户输入

v-on事件绑定

组件化应用构建

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树

  • 与自定义元素的关系

    Web Components 规范已经完成并通过,但未被所有浏览器原生实现。目前 Safari 10.1+、Chrome 54+ 和 Firefox 63+ 原生支持 Web Components。相比之下,Vue 组件不需要任何 polyfill,并且在所有支持的浏览器 (IE9 及更高版本) 之下表现一致。必要时,Vue 组件也可以包装于原生自定义元素之内。 Vue 组件提供了纯自定义元素所不具备的一些重要功能,最突出的是跨组件数据流、自定义事件通信以及构建工具集成。

vue精讲

vue实例

vue生命周期

  • beforeCreate

    实例初始化之后,观测数据和事件配置之前

  • created

    创建实例之后立即被调用,数据观测和事件配置已完成,挂载阶段为开始el属性不可见

  • beforeMount

    挂载之前,相关渲染函数首次被执行

  • mounted

    el被新创建的vm.$el替换挂载成功

  • beforeUpdate

    数据更新之前调用

  • updated

    组建dom都更新,组建更新完毕

  • beforeDestroy

    实例销毁之前

  • destroyed

vue模版语法

  • v-once

    只执行一次

  • v-html

    将内容编译成html代码

  • v-text

    类似模版字符串,不支持html代码

  • v-once

    只执行一次

  • 插值

    只执行一次

    • 文本

      {{}}数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值 也可以使用v-once 指令

      • {{}}
      • v-once
    • 原始 HTML

      v-html使用的时候需要注意。不要将用户信息使用动态v-html渲染吗,容易收到ssr的攻击

    • Attribute

      可以使用v-bind的方式去调用,可以动态使用某种方法或者属性 动态地绑定一个或多个特性,或一个组件 prop 到表达式

    • 使用 JavaScript 表达式

      支持三元判断进行js的校验

  • 指令

    • 参数

      一些指令能够接收一个“参数”,在指令名称之后以冒号表示 绑定后续中为事件或者属性的名字

    • 动态参数

      可以用方括号括起来的 JavaScript 表达式作为一个指令的参数 这里的 attributeName 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的 Vue 实例有一个 data 属性 attributeName,其值为 "href",那么这个绑定将等价于 v-bind:href。

      • 动态参数值的约束

        动态参数预期会求出一个字符串,异常情况下值为 null。这个特殊的 null 值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。

      • 动态参数表达式的约束

        因为某些字符,如空格和引号,放在 HTML attribute 名里是无效的。

    • 修饰符

      修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()

  • 缩写

    • v-bind
    • v-on

计算属性,监听器

  • computed

    初始化不需要给值,有缓存

    • 计算属性的get和set

      get获取数据 set设置

  • watch

    需要初始值,如果两者都可以实现的话,使用computed

  • 方法

Class 与 Style 绑定

  • class

    • 对象语法
    • 数组语法
  • style

    • 对象语法
    • 数组语法

条件渲染

  • v-if

    v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。 v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

    • 不推荐同时使用 v-if 和 v-for。请查阅风格指南以获取更多信息。
  • v-show

    相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

  • input中的key值

    可以清空内容

列表渲染

v-for=‘ item of itemArr’

  • 用 v-for 把一个数组对应为一组元素

    我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。

  • 在 v-for 里使用对象

    接受3个参数(value, name, index) 在遍历对象时,会按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。

  • 维护状态

    不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。

  • 数组更新检测

    • 变异方法

      push pop sheift unshift splice sort reverse

    • 替换数组

      filter()、concat() 和 slice() 。它们不会改变原始数组,而总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组

    • 注意事项

      • 由于 JavaScript 的限制,Vue 不能检测以下数组的变动:

        • Vue.set(vm.items, indexOfItem, newValue)
        • vm.items.splice(indexOfItem, 1, newValue)
  • 对象变更检测注意事项

Vue.set(object, propertyName, value) 
	- 多个对象修改

	  vm.userProfile = Object.assign({}, vm.userProfile, {
	    age: 27,
	    favoriteColor: 'Vue Green'
	  })
  • 显示过滤/排序后的结果

    • 有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际改变或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。

      • 使用计算属性
      • 使用方法,将数组作为参数传入
  • v-for

    • 来循环渲染一段包含多个元素的内容。
  • v-for 与 v-if 一同使用

    • 注意我们不推荐在同一元素上使用 v-if 和 v-for

      v-for要比v-if 优先级要高

  • 当在组件上使用 v-for 时,key 现在是必须的。

事件处理

  • 监听事件v-on||@

  • 事件修饰符

    • stop

      • 阻止单击事件继续传播(阻止冒泡)
    • prevent

      • 消除浏览器模式事件
    • .capture

      • 添加事件监听器时使用事件捕获模式
    • self

      • 即事件不是从内部元素触发的
    • once

    • passive

深入理解vue组建

组建使用中的细节点

  • is

    js中某些标签固定用法,例如:tabel>tbody>tr>td,ul>li 此情况下组建可使用is属性

  • data使用函数(除根实例)

    根组建中使用对象是因为他只调用一次 组建中考虑到复用性,使用对象的话,他是引用类型,一个改变,其他都会响应,所以使用函数返回对象,避免互相影响,污染。内部数据保持独立数据储存

  • ref

    • dom

      在vue中我们不建议操作dom,.但是有些动画需要操作时,我们可以使用ref获取dom的引用。

    • 组建

      在组建中使用ref时。我们获取的是就是组建的引用

父子组建的数据传递

  • 父-子

    通过props属性进行传值。值可以是对象,数组,字符串等方式,单项数据流,子组建不能修改父组建传入的值。因为其他的地方也可以能会引用组建,。一个修改,其他的地方也可以会影响。

  • 子-父

组建参数校验与非组建porps特性

  • porps接受类型

    可以接受多种类型,比如对象,数组,字符串等 接受中可以扩展, type:数据类型 require:是否必须传 defult:默认值 validator:自定义校验函数

  • porps特性

    父传子:子组建接受,不会显示在dom标签上。

  • 非porps特性

    父组建传旨,子组建未接收,会报错。 不实用会直接显示在dom节点(html上)

给组建绑定原生事件

给事件绑定时加上@click.native='fn'

非父子组建传旨

  • eventBus

    使用事件总线机制,实现组建间传旨,通过在vue的原型上挂载属性,然后指向实例,这样bus上就具备vue实例上的方法了,在任何时候都可以获取

在vue中使用插槽

  • vue中插槽的使用

    组建中插入标签,子组建中使用插槽解决

    <ps content='youzi'>
        <header slot="header">我是header</header>
        <!-- <p>我是一只小毛驴</p> -->
        <footer slot="footer">我是footer</footer>
      </ps>
    </div>
    <script>
      Vue.component('ps', {
        template: `<div>
            <slot name='header'></slot>
            <p>哈哈哈哈</p>
            <slot name='footer'></slot>
          </div>`
      })
    
  • 具名插槽

    使用solt属性添加名字,子组建中使用name名字去获取即可

  • 默认插槽

    父组建可不写内容,子组建使用《solt》《/solt》去展示内容即可

作用域插槽

  • 默认插槽

    父组建可不写内容,子组建使用《solt》《/solt》去展示内容即可

vue中的的动画效果

单元素/组件的过渡

当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理: 自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。 过果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。 果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同)

过渡的类名

  • v-enter

    定义进入过渡的开始状态,在元素被插入之前生效。在元素被插入之后的下一帧移除。

  • v-enter-active

    定义过渡生效时的状态,整个过渡状态中都会被应用,动画结束之后移除, 这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

  • v-enter-to

    定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

  • v-leave

    定义离开过渡的开始状态

  • v-leave-active

    定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

  • v-leave-to

    定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

CSS 过渡

CSS 动画

CSS 动画用法同 CSS 过渡,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。

自定义过渡的类名

可以通过name属性进行绑定类名 或者enter-active-class leave-active-class

在vue中使用animate.css库

引入animate。js,绑定enter-active-class=‘animated 动画类名’ leave-active-class='animated 动画类名'

同时使用过渡和动画

使用animate。css在transition标签上绑定class的名字,然后将过渡的动画名字也加上 你就需要使用 type attribute 并设置 animation 或 transition 来明确声明你需要 Vue 监听的类型。

初始渲染的过渡

使用appear 使用appear-active-class

显性的过渡持续时间

可以直接使用数值 也可以接受对象,里面可以分别设置enter和leave的过渡时常

多个元素的过渡

可以使用三元判断或者switch

过渡模式

 的默认行为 - 进入和离开同时发生。 两个按钮都被重绘了,一个离开过渡的时候另一个开始进入过渡。 可以通过mode去设置,有2个属性,一个out-in,一个是in-out

多个组件的过渡

多个组件的过渡简单很多 - 我们不需要使用 key attribute。相反,我们只需要使用动态组件: 当组建动态渲染的时候,因为进入和离开同时发生。,当一个离开的时候过渡,另一个进入的时候过渡,所以需要添加属性去操作mode='out in'

列表过渡

  • 不同于 ,它会以一个真实元素呈现:默认为一个 。你也可以通过 tag attribute 更换为其他元素
  • 过渡模式不可用,因为我们不再相互切换特有的元素。
  • 内部元素 总是需要 提供唯一的 key 属性值。
  • CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。

首页项目

问题

  • swiper默认显示的图片是第4个,而非第一个

    问题 由于当swiper还未ajax请求数据的时候,是由外层传入的空数组显示的 swiper是空数组创建的,所以默认显示最后一个 解决 加个数组的length判断,此处需注意,避免在节点的v-if中做过多逻辑判断,

  • UI组建穿透

    使用/deep/去解决

  • 页面未加载出来,页面有数据后出现抖动效果

    问题 图片没加载出现高度是0,页面会有抖动, 解决 外层设置div标签将其包裹 width:100% height:0 overflow:hidden padding-bottom:图片的比例(高/宽)% 使用vh,vw width:100% height:(高/宽)vw

  • swiper图片2页轮播

    使用计算属性,将原来一维数组换成2维数组,根据数组的长度/一页展示的内容 const pages = [] this.list.forEach((item, index) => { const page = Math.floor(index / 8) if (!pages[page]) { pages[page] = [] } pages[page].push(item) }) return pages

  • axios

    在用需要的组建加载,不要通过Vue.use(axios)

    • 使用

      局部组建引入 import axios from 'axios' 请求axios.get('dsdsd') 全局引入,绑定到原型上 import axios from 'axios' Vue.prototype.axios = axios

  • mock

    使用mock数据的时候,vue-cli2和vue-cli3的区别是,vue-cli3去除了static文件夹,现在静态资源我们都放到了public中

优化

  • 抽离全局样式
  • 抽离公共css

项目初始化准备

多页面应用

表现:页面跳转都会更新页面。更改页面会重新加载页面 好处: 页面首屏加载时间快,由于服务器返回一个html文件,只经历了一次http请求。 seo效果好,由于搜索引挚可以识别html代码,对网页排名,网页内容权重有比较好的优化 缺点: 页面切换慢

单页面

但页面不会请求多次,js通过url感知变化,动态将js所需要的页面挂载上 前端做路由。不会每次请求,也不重新加载页面。 好处: 页面切换时间快 页面跳转,js渲染 缺点: 首屏加载时间比较慢,seo差, 因为页面不仅要进行一次html请求,同时发送js的请求,2这都回来才会将页面内容展示 由于ssr是服务端渲染,而但页面是客户端渲染请求数据动态添加上的。所以seo并不能查看到数据

移动端适配方案

  • lib-flexible+postcss-px2rem

    libn-flexible原理: 通过获取页面的布局视口,然后分成10分,比如375,375/10=37.5.;1rem=37.5px. 拿到的设计图元素是75,75/37.5=2rem。 document.documentElement.getBoundingClientRect().width/10 因为rem是根据根元素(html)节点的font-size去计算的,所以我们只需要统一设置font-size即可 我们可以借助PostCSS的px2rem插件来帮助我们完成这个过程。 当触发了window的resize和pageShow事件之后自动调整html的fontSize大小。

    • yarn add lib-flexible postcss-px2rem

    • 在main.js总引入import 'lib-flexible'

    • 将项目/public/index.html中的设置视口的meta删除和注释删除

    • 根路径创建vue.config.js,其中设置postcss-px2rem

      // vue.config.js module.exports = { css: { // 启用 CSS modules modules: false, // 是否使用css分离插件 extract: true, // 开启 CSS source maps? sourceMap: false, // css预设器配置项 loaderOptions: { css: {}, postcss: { plugins: [ //remUnit这个配置项的数值是多少呢??? 通常我们是根据设计图来定这个值,原因很简单,便于开发。 //假如设计图给的宽度是750,我们通常就会把remUnit设置为75,这样我们写样式时,可以直接按照设计图标注的宽高来1:1还原开发。 require('postcss-px2rem')({ remUnit: 75 }) ] } } } }

  • vh、vw方案

    • yarn add -D postcss-px-to-viewport

    • 在config设置css配置项

      module.exports = { css: { loaderOptions: { postcss: { plugins: [ require("postcss-px-to-viewport")({ viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750. viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334. unitPrecision: 3, // (指定px转换为视窗单位值的小数位数(很多时候无法整除). viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw. fontViewportUnit: "vw", selectorBlackList: [], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名. minPixelValue: 1, // 小于或等于1px不转换为视窗单位,你也可以设置为你想要的值. mediaQuery: false, // 允许在媒体查询中转换px. replace: true, exclude: /(/|\)(node_modules)(/|\)/, }) ] } } } }

重置CSS

使用插件库reset.css

移动端1px边框问题

移动端点击事件延迟处理

列表页开发

betterScroll.js

实现页面滚动

城市首字母滚动

首先获取A距离顶导的距离 this.$refs['A'][0].offsetTop; 获取手指滑动距离顶部的距离。 e.touches[0].clientY - 72(导航的高度) 当前索引(index) index=Math.floor((clientY - this.startY) / 17); 17是每个字母的高度

性能优化

  • 使用update将固定数据保存起来,比如A元素距离顶部的距离。

  • 采用截流函数(滑动改变位置+搜索的时候)

  • keep-alive

    将已经加载过的数据存入内存,避免多次渲染消耗性能 使用后vue会多处2个生命周期钩子函数 activated deactivated在页面退出的时候去使用

  • 页面使用vuex改变数据的时候,刷新数据无法保存?

    使用localstorge

vuex

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state:{city:'北京'},
	actions:{
		changeCity:({commit},val)=>{
				commit('changeCity',val)
		}
	},
    mutations:{
		changeCity(state,val){
			state.city=val		
		}
	}

})
  • state

    相当于一个独立的储存空间,公共数据存放的地方 在组建中使用2种方式。 this.$store.state.xxx this.city

      	```					
      		import { mapState } from 'vuex'
    			computed: {
    		...mapState(['city'])
      		  },
      	```
    
  • actions

    异步操作改变数据,批量操作放到这里,相当于一个事件触发器 使用方法: 组建触发通过this.state.dispatch(''changeCIty,'item.name') import {mapActions} from 'vuex' methods: { handleCityClick (val) { this.changeCity(val) this.router.push('/') }, ...mapActions(['changeCity'])}

  • mutations

    actions通过commit调用mutations,改变数据。

  • Getter

    类似vue中的计算属性,比如同时用到state的数据,可以用getter做拆分,避免数据泰国冗余

  • Module

    对于大型项目,页面数据量大的情况下,可以将每个组建所需要的数据单独拿出作为一个模块去使用。最后去拼合

nuxt框架中vuex写法修改

直接导出export const modules = { geo, home, user } 不需要在new Vuex.store(modules:{})去定义了

详情页开发

公共画廊组建使用swiper动态传数据页面滑动有问题

  • 原因

    一开始我们的组建除于一个隐藏的状态,再次将他展示出来的时候,swiper计算宽度会有问题,导致轮播图无法正常运行

  • 解决

    在swiperoptions上添加2个属性, observeParents:true, observer:true 当窗口发生变化时,更新swipe,监听到父级发生变化时,动态自我更新

实现heade的渐隐渐显的内容

设置2部分内容,通过v-show去判断展示哪一个, 渐隐渐显主要利用document.documentElement.scrollTop&&document.body.scrollTop去计算滚动的位置改变效果

对全局事件的解绑

如果绑定在某一个组建的元素上面不会产生影响 但是绑定到了全局window上,无论在那个组建都会收到影响 在我们使用keep-aliveb包裹组建的时候,会有2个新增生命周期函数, activated(缓存被激活的时候使用) deactivated(组建被隐藏的时候去调用) window.removeEventListener(‘’)

使用递归组建实现详情页列表