vue

vue的入门

      • 什么是vue?
      • 介绍
        • MVVM
        • 生命周期函数
        • 声明渲染,条件渲染,列表渲染
        • 模板指令
        • 双向绑定v-model
        • 计算属性,数据观测,方法
        • 事件绑定,修饰符
        • 组件
        • 路由
        • 路由守卫
        • 路由懒加载
        • 动态组件,缓存组件
      • 组件通讯
        • 正向数据流,父 -> 子 通过props传递
        • 反向数据流,子 -> 父 使用 $emit
        • 父子组件数据共享 使用$refs $parent
        • 兄弟之间传值 公共总线 eventBus
        • 使用$root设置全局属性
        • 订阅发布模式(第三方库 pubsub )
        • 状态管理 Vuex
      • 自定义事件,自定义指令
      • 第三方插件引入与使用(UI库)

什么是vue?

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

介绍

Vue是一套用于构建用户界面的渐进式框架。基于数据驱动,一些都是数据,面向数据。

MVVM

Vue是一个MVVM的框架。
Mvvm定义MVVM是Model-View-ViewModel的简写。即模型-视图-视图模型。
【模型】指的是后端传递的数据。
【视图】指的是所看到的页面。
【视图模型】mvvm模式的核心,它是连接view和model的桥梁。
它有两个方向:
一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。
二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。
实现的方式是: DOM 事件监听。这两个方向都实现的,我们称之为数据的双向绑定。
总结:在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。

生命周期函数

beforeCreate(创建前) 在数据观测和初始化事件还未开始

created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来

beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。
注意此时还没有挂载html到页面上。

mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。
完成模板中的html渲染到html页面中。此过程中进行ajax交互。

beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。

updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。
然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。

beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。

destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

简述每个周期具体适合哪些场景?
1、beforeCreate:可以在这加loading事件,在加载实例时触发。
2、created:初始化完成时的事件写在这里,如在这里结束loading,异步请求也适合在这里调用。
3、mounted:挂载元素,获取到dom节点。
4、updated:如果对数据统一处理,在这里写上相应的函数。
5、beforeDestroy:可以做一个确定停止事件的确认框。

声明渲染,条件渲染,列表渲染

vue_第1张图片
这里涉及到一些模板指令,后面会统一说一下模板指令

模板指令

{{数据名}} 模板 mustche 插值表达式 声明式渲染

v-text=“数据名” vue特有的属性(指令)

v-html=“strong” 非转义输出

v-for="(val,index) in 数据"
val值 index索引 变量数组、对象
默认 :key=“index” 指定key 是个bmw字符 vue是认得 修改VDom的key值
:key=“item.id” 指定key 是数据id(唯一性) 修改VDom的key值
key的优势: 避免数据错乱导致的视图问题,提供性能
属性绑定:
v-bind:html属性=“数据” 普通的html属性绑定数据
:html属性=“数据” 简写 title/src/url/…
事件:
v-on:事件名=“方法”
@事件名=“方法” 简写
@事件名=“方法(参数)”
@事件名=“方法($event,参数)” methods:{方法:function(ev,参数){ev/event}}

 注意:vue提供的选项的值如果是函数时,不可用箭头函数

样式操作|属性绑定
v-bind:class=“数据|属性|变量|表达式”
:class/style = " 数据 " 数据类型:字符/对象 / 数组
:class="{类名:true,类名2:false}" 布尔值决定样式是否使用
:style="[{css属性名:值},{css属性名小驼峰:值}]"


指令: 扩展了html语法功能,区别了普通的html属性
vue自带的指令: v-text/v-html/v-bind/v-for/v-model/v-on

		v-show="布尔" 			v-if="布尔"
区别:	操作css					操作dom
场景:	适合频繁切换		    适合不频繁切换
性能:	初始渲染消耗			频繁切换回有消耗

其他指令: https://cn.vuejs.org/v2/api/#指令

指令(directive):
	v-once 渲染一次
	v-pre  原样输出,不编译
	v-cloak 防闪烁

双向绑定v-model

vue_第2张图片
可以看一下双向绑定的原理(百度或者官网)

计算属性,数据观测,方法

首先页面首次加载
vue_第3张图片
点击按钮触发
vue_第4张图片
这里可以得出
计算属性: 是一个函数,所依赖的元数据变化时,会再次执行,平时会缓存,是响应式的,需要在模板中渲染才可调用
computed:{
计算属性: function(){return 返回值} 使用: {{计算属性}}
}

与methods的区别:	方法会每次调用,计算属性不会
		计算属性的性能高: 适合做筛选,基于它们的响应式依赖进行缓存的
		方法:适合在列表渲染使用,强制渲染执行

属性检测|数据观测: 需要在数据变化时执行异步或开销较大的操作时

watch:{
	数据名:'methods函数名'    数据名==data的数据
	数据名:函数体(new,old)
	数据名:{
		handler:fn(new,old),
		deep: true 深度检测  默认 false
		immediate: true 首次运行  默认false
	}
}

计算属性 vs 属性检测

计算属性computed: 	首次运行   		调用时需要在模板中渲染,修改计算所依赖元数据		默认深度依赖		适合做筛选,不可异步
属性检测watch: 		首次不运行		调用时只需修改元数据								默认浅度观测		适合做执行异步或开销较大的操作

事件绑定,修饰符

绑定行间事件:

原理:

vue事件是事件绑定

绑定行间事件:		
        

修饰符:
事件|自定义事件修饰符: @click.stop.prevent
capture: 使用事件捕获模式
self: 点到时才触发,不是从内部元素触发的
once: 只会触发一次
passive: onScroll事件 结束时触发一次,不会频繁触发,移动端使用
native 作用与自定义组件

按键修饰符:	@keyup.left/13
	系统键	.ctrl
			.alt
			.shift
			.meta
			exact 严格默认   @键盘事件.修饰符1.修饰符2.exact    只有1+2才可触发

鼠标按钮修饰符:
	.left
	.right
	.middle

表单修饰符: 
	v-model.lazy   :  	确认时才修改model数据
	v-model.number :	提取数子
	v-model.trim :	 删除前后空格

组件

Vue根实例表示1个应用,一个应用有若干个组件拼装而成

使用组件
	<组件名>
	<组件名/>  需要模块化环境支持
	
脚手架环境下webpack协助解决了,调用时依然不能小写header 定义组件 定义: a) let 组件变量名= Vue.extend({ template:'
我是header组件
' }); b) let 组件变量名={}; √ 注册(拼装) a) Vue.component('组件名',组件变量名); 全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生 b) 选项 components:{ 组件名:组件变量名 √ } 组件数据 data 要是个函数,且要有返回值 object 一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝,否则组件复用时,数据相互影响 单文件组件(.vue) script + template + style 注意: 组件名不可和html同名 组件没有el选项,只有根实例存在el 组件的模板一定要有根元素 组件的data是个函数 推荐: 组件变量名: 大驼峰 XxxXxx 组件名: xx-xx | 大驼峰(模块化环境)

路由

SPA: single page application   单页面应用

特点: 速度快,数据ajax请求,通过路由,页面不会整体重载
实现:  路由 ->  根据url的不同,加载组件

使用流程:

	-1. 安装 : npm i vue-router -S
	0.	import VueRouter from 'vue-router' -> Vue.use(VueRouter) 安装|注册到全局
	1. 使用路由 (去哪)
		首页
  		展示区
  		router-link 组件属性
  			to="/home" 
			tag='li' 指定编译后的标签
			active-class='类名' 指定激活后的样式
	2. 配置路由(建立组件和请求的对应关系)	数组
		[{path:'/home',component:home},,{}]
		path 路径
		component: 指向的组件变量名
	3. 创建路由(传递配置)
		router = new VueRouter(配置)
		配置:	{routes:数组}
	4. 顶层|根组件,注册路由 (路由控制页面组件的加载)
		选项
			router(选项):router (router对象)
	子路由:children
		routes=[
			{},
			{
				path:xx
				component:xx
				children:[  子路由
					{}
					..
				]
			},
			{}
		]

vue_第5张图片

路由守卫

        导航守卫: 路由授权|守卫

		全局守卫/路由独享的守卫/组件内的守卫

		beforeRouteEnter(to,from,next){}	前置守卫,进入
			to 目标路由
			from 当前路由
			next 是个函数  next() == next(true)  运行跳转
						   next(false) 不让跳转
						   next('字符路径')/next({对象路径}) 重定向

		beforeRouteLeave(to,from,next){}  后置守卫,离开

	路由数据预载:
		beforeRouteEnter(to,from,next){
			1. 数据附加到目标路由上 to.query.数据名=值
			2. next( _this => _this.属性="拿到的数据")   √
		}

路由懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
方式一:

const Foo = () => import('./Foo.vue')

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

方式二:

const ImportFuncDemo = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo')
 const ImportFuncDemo2 = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo2')

export default new Router({
    routes: [
        {
            path: '/importfuncdemo1',
            name: 'ImportFuncDemo1',
            component: ImportFuncDemo1
        },
        {
            path: '/importfuncdemo2',
            name: 'ImportFuncDemo2',
            component: ImportFuncDemo2
        }
    ]
})

动态组件,缓存组件

动态组件: 组件动态化(数据化),在不同组件之间进行动态切换,component自身不会渲染

    
	

缓存组件:
keep-alive 包裹了目标组件,对目标组件缓存,不会触发卸载挂载,但会触发activated/deactivated
keep-alive 不给属性时,默认内部出现过得组件所组成的视图,都会被缓存,初始缓存第0个组件

属性:
	:include: ['组件名','组件名2']  加入一部分
	:exclude: ['组件名','组件名2']  排除一部分
	:max = 数字   最多可缓存的组件数
		最多可以缓存多少组件实例。一旦这个数字达到了,
		在新实例被创建之前,已缓存组件中最久没有被访问
		的实例会被销毁掉(卸载挂载)。
组件钩子:
	activated  活动组件  被缓存时起效果
	deactivated 非活动组件
场景:
	keep-alive 包裹 component | router-view

vue_第6张图片

组件通讯

正向数据流,父 -> 子 通过props传递

vue_第7张图片
vue_第8张图片
这里父组件给两个组件都吃传递数据,child1正确接收,但是child是可以做类型校验的,当父组件传递数据的格式进行校验,类型不一致报错,以及当父组件没有传值是,也可以给默认值。

反向数据流,子 -> 父 使用 $emit

vue_第9张图片

子->父  事件(自定义)
		<子 @自定义事件="父方法">
		子:		this.$emit('自定义事件',子.数据名)
		父:		methods-> 父方法(接受数据){处理}

父子组件数据共享 使用$refs $parent

  父子之间共享数据和方法
		<子 ref="自定义子名称">
		父访问子:	this.$refs.自定义子名称.数据名/方法()
		子访问父:	this.$parent.数据名/方法()
		$refs 只会在组件渲染完成之后生效,并且它们不是响应式的,避免在模板或计算属性中访问 $refs

vue_第10张图片

兄弟之间传值 公共总线 eventBus

vue_第11张图片

特别注意:$emit和$on的事件必须在一个公共的实例上,我们可以使用一个空的 Vue 实例作为中央事件总线。
Vue.prototype.$player = new Vue()

this.$player.$emit('自定义的事件名',数据)
this.$player.$on('自定义的事件名',function(接){处理})

使用$root设置全局属性

let app = new Vue({
    el: '#app',
    // 全局数据,在其他页面或者组建可改变
    data: function () {
    return {
        s: ''
    }
    }, 
    router,
    store,
    template: ''
})

组件内部
console.log(this.$root.s)  // 设置了s属性

订阅发布模式(第三方库 pubsub )

  1. 首先安装pubsub-js
npm install --save pubsub-js

2.订阅方组件

PubSub.subscribe('deleteTodo',(msg,index)=>{
    console.log(index)  
  });
  1. 发布方组件
 PubSub.publish('deleteTodo', 111);  //deleteTodo一定要与订阅方名称一样,index是通信的具体数据

vue_第12张图片

状态管理 Vuex

场景: 打算开发中大型应用
特点: 集中式数据管理, 一处修改,多处使用

思维:
										store
				this.$store.commit('increment')	-> mutations
				this.$store.dispatch('jia')		-> actions
			     mapActions() ->actions							mapGetters('类型')->getters
			学生			代课老师			校长		 	财务     	班主任		学生
		components - >  actions		->  mutations -> state  <- getters	<-	components
			发送请求      处理			修改状态
						  业务逻辑		修改state			   读取state
						  异步
						  							state<-$store.state <-  学生

简单使用步骤

安装: npm i vuex -s

引入

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

//挂载Vuex
Vue.use(Vuex)

//创建VueX对象
const store = new Vuex.Store({
    state:{
        //存放的键值对就是所要管理的状态
        name:'helloVueX'
    }
})
export default store

注册

import store from './store/index'

new Vue({
  render: h => h(App),
  router,
  store,
  data(){
    return {
      msg: 111
    }
  }
}).$mount('#app');

这里在组件里就可以获取到状态管理里面的数据了。
组件内部通过
vue_第13张图片
核心内容:
在VueX对象中,其实不止有state,还有用来操作state中数据的方法集,以及当我们需要对state中的数据需要加工的方法集等等成员。

成员列表:
state 存放状态
mutations state成员操作
getters 加工state成员给外界
actions 异步操作
modules 模块化状态管理

首先,Vue组件如果调用某个VueX的方法过程中需要向后端请求时或者说出现异步操作时,需要dispatch VueX中actions的方法,以保证数据的同步。可以说,action的存在就是为了让mutations中的方法能在异步操作中起作用。

如果没有异步操作,那么我们就可以直接在组件内提交状态中的Mutations中自己编写的方法来达成对state成员的操作。

注意,不建议在组件中直接对state中的成员进行操作。

state
对于数据集中管理,可以理解为仓库
mutations
操作state数据的方法的集合,比如对该数据的修改、增加、删除等等。

mutations方法都有默认的形参:
([state] [,payload])
state是当前VueX对象中的state
payload是该方法在被调用时传递参数使用的

Getters
可以对state中的成员加工后传递给外界

Getters中的方法有两个默认参数
state 当前VueX对象中的状态对象
getters 当前getters对象,用于将getters下的其他getter拿来用

vue_第14张图片
vue_第15张图片
Actions
由于直接在mutation方法中进行异步操作,将会引起数据失效。所以提供了Actions来专门进行异步操作,最终提交mutation方法。

Actions中的方法有两个默认参数

context 上下文(相当于箭头函数中的this)对象
payload 挂载参数

vue_第16张图片
可以看到在2s后数据发生改变
vue_第17张图片
Models
当项目庞大,状态非常多时,可以采用模块化管理模式。Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

models:{
    a:{
        state:{},
        getters:{},
        ....
    }
}

mapActions/mapGetters

执行后, 返回来的是对象
对象:	{incremen:fn,decrement:fn,xx,xx}

mapGetters 用来接管 computed的
	computed:mapGetters(['类型1','类型2'])
mapActions 用来接管 methods的
	methods:mapActions(['类型1','类型2'])

vue_第18张图片
vue_第19张图片

自定义事件,自定义指令

自定义事件
绑定自定义事件:

	绑定:vm|组件.$on( '自定义事件名'|['自定义事件名1','自定义事件名2'], 回调(参数) )
		  <自定义组件  @|v-on:自定义事件
	销毁:vm.$off( '自定义事件名'|['自定义事件名1','自定义事件名2'])
	触发: vm.$emit(自定义事件名,参数)

自定义事件名: 使用 kebab-case 的事件名

	场景: 在一个组件实例上手动侦听事件时

	特点:  只有绑定方才可以触发
		   自定义的组件 触发自定义的事件需要native修饰符
		   自定义组件 可以使用v-on或@自定义事件

自定义指令
自定义指令: 指令是个函数|对象,用来操作dom的, 里面的this 返回window

	a)全局:	Vue.directive('指令名不带v-',函数(el,binding))
		el == 使用指令的DOM元素
		binding 是个对象 含有传入的 参数(binding.value)
	b)局部:  定义在选项里面
		directives:{
			指令名不带v-	: 函数(el,binding){}
		}

	指令是个函数(简写),可以是个对象

	{
		钩子函数
		inserted:fn(el,binding)		绑定指令的元素插入到父节点时调用
		bind:fn	指令第一次绑定到元素时调用
		update:fn	指令所在的元素的model层的数据,view有更新请求时
		componentUpdated:fn	更新完成时
	}

	简写方式: bind + update
	Vue.directive("val",function(el,bind){
		el.value=bind.value.max-bind.value.value;
	})

vue_第20张图片

第三方插件引入与使用(UI库)

elementUI:
	官网:http://element.eleme.io

	安装+全局引入

	安装:	npm i element-ui -S

	全局引入:
		import ElementUI from 'element-ui';
		import 'element-ui/lib/theme-chalk/index.css';

		Vue.use(ElementUI);

	按需引入:

		npm install babel-plugin-component -D

		修改babel配置 baberc|babel.config.js

		添加:
			"plugins": [
			    [
			      "component",
			      {
			        "libraryName": "element-ui",
			        "styleLibraryName": "theme-chalk"
			      }
			    ]
			  ]

		a) 全局使用:   所有应用内部组件直接使用 
			import { Button } from 'element-ui';
			Vue.component(Button.name, Button); | Vue.use(Button)

		b) 组件内部使用: 只有当前组件可使用
			import { Select, Option } from 'element-ui';
			components:{
			    'bulala':Select,
			    [Option.name]:Option,
			  },

你可能感兴趣的:(vue,vue.js)