- 建立前/后:在
beforeCreated
阶段, 实例的挂载元素$el
和数据对象data
以及事件还未初始化。- 在
created
阶段,Vue
实例的数据对象data
以及方法的运算有了,$el
尚未。- 载入前/后:在
beforeMount
阶段,render
函数首次被调用,Vue
实例的$el
和data
都初始化了,但仍是挂载在虚拟的DOM
节点上。- 在
mounted
阶段,Vue
实例挂载到实际的DOM
操做完成,通常在该过程进行Ajax
交互。 更新前/后:在数据更新以前调用,即发生在虚拟DOM
从新渲染和打补丁以前,调用beforeUpdate
。- 在虚拟
DOM
从新渲染和打补丁以后,会触发updated
方法。- 销毁前/后:在执行实例销毁以前调用
beforeDestory
,此时实例仍然能够调用。- 在执行
destroy
方法后,对data
的改变不会再触发周期函数,说明此时Vue
实例已经解除了事件监听以及和DOM
的绑定,可是DOM
结构依然存在。
首先建立一个vue
实例,Vue()
;html
在建立Vue
实例的时候,执行了init()
,在init
过程当中首先调用了beforeCreate
。前端
Created
以前,对data
内的数据进行了数据监听,而且初始化了Vue
内部事件。具体以下:vue
完成了数据观测;node
完成了属性和方法的运算;jquery
完成了watch/event
事件的回调;ios
可是此时还未挂载dom
上,$el
属性是不可见的;git
beforeMount
以前,完成了模板的编译。把data
对象里面的数据和vue的语法写的模板编译成了html
,可是此时尚未将编译出来的html
渲染到页面;github
template
属性的时候,直接用内部的,而后调用render
函数去渲染。template
,就调用外部的html(“el”option(选项))
。实例内部的template
属性比外部的优先级高。 render
函数 > template
属性 > 外部html
;Mounted
以前执行了render
函数,将渲染出来的内容挂载到了DOM
节点上。mounted
是将html
挂载到页面完成后触发的钩子函数;当mounted
执行完毕,整个实例算是走完了流程;在整个实例过程当中,mounted
仅执行一次;面试
beforeUpdate
:数据发生变化时,会调用beforeUpdate
,而后经历virtual DOM
,最后updated
更新完成;ajax
beforeDestory
是实例销毁前钩子函数,销毁了全部观察者,子组件以及事件监听;
destoryed
实例销毁执行的钩子函数;
若是有子组件的话,那么调用顺序为:
父beforeCreate
-> 父created
-> 父beforeMount
-> 子beforeCreate
-> 子created
-> 子beforeMount
-> 子mounted
-> 父mounted
Vue
生命周期?Vue
实例从建立到销毁的过程,就是生命周期。从开始建立、初始化数据、编译模板、挂载 DOM
-> 渲染、更新 -> 渲染、销毁等一系列过程,称之为 Vue
的生命周期。
Vue
哪几个钩子?会触发 4 个生命钩子:建立前/建立后、挂载前/挂载后
复制代码
DOM
渲染在哪一个周期就已经完成?在 beforeMounted
时它执行了 render
函数,对$el
和 data
进行了初始化,但此时仍是挂载到虚拟的DOM
节点,而后它在 mounted
时就完成了 DOM
渲染,这时候咱们通常还进行 Ajax
交互。
Vue
的渲染过程vue
模板的本质是字符串,利用各类正则,把模板中的属性去变成 js 中的变量,vif
,vshow
,vfor
等指令变成 js 中的逻辑render
函数render
函数执行返回 vNode
vNode
的 path
方法把 vNode
渲染成真实 DOM
Vue
的整个实现流程render
函数,把模板中的属性去变成 js 中的变量,vif
,vshow
,vfor
等指令变成 js 中的逻辑render
函数,在初次渲染执行render
函数的过程当中 绑定属性监听,收集依赖,最终获得 vNode
,利用 vNode
的 Path
方法,把 vNode
渲染成真实的 DOM
render
函数,不过这个时候就不须要绑定属性和收集依赖了,最终生成新的vNode
vNode
和 旧的 vNode
去作对比,找出真正须要更新的 DOM
,渲染Vue
的响应式原理Vue 内部使用了 Object.defineProperty()
来实现数据响应式,经过这个函数能够监听到set
和 get
的事件。
1)首先利用 Object.defineProperty()
给 data
中的属性去设置 set
, get
事件 递归的去把 data
中的每个属性注册为被观察者
2)解析模板时,在属性的 get
事件中去收集观察者依赖
3)当属性的值发生改变时,在 set
事件中去通知每个观察者,作到所有更新
vue vue-router
路由 vuex axios
1)父传子
过程
2)子传父
本质上是父组件使用子组件的数据
this.$emit('自定义事件名',this.qqq)
传递子组件的数据import Vue from 'vue'
const component = {
props: ['value1'],
template: `
<div>
<input type="text" @input="handleInput" :value="value1">
</div>
`,
data () {
return {
}
},
methods: {
handleInput (e) {
this.$emit('input', e.target.value)
}
}
}
new Vue({
components: {
CompOne: component
},
el: '#root',
template: `
<div>
<comp-one :value1="value" @input="value = arguments[0]"></comp-one>
</div>
`,
data () {
return {
value: '123'
}
}
})
复制代码
3)非父子组件间的数据传递
兄弟组件传值eventBus
,就是建立一个事件中心,至关于中转站,能够用它来传递事件和接收事件。
4)假设在工做中,有三个 .vue 文件:A.vue、B.vue、C.vue。A.vue 是主页面,B.vue 和 C.vue 相似于头部导航条和底部导航栏。如今,B.vue 点击会切换路由,C.vue 须要获取 B.vue 传递的信息。
A.vue
<template>
<div>
<top-nav></top-nav>
<div class="container">
<router-view></router-view>
</div>
<bottom-nav></bottom-nav>
</div>
</template>
复制代码
bus.js
import Vue from 'vue';
// 使用 Event Bus
const bus = new Vue();
export default bus;
复制代码
B.vue
<template>
<div class="bottom-nav">
<div class="nav-one" @click="goToPage({path: '/HomeIndex', meta:'首页'})">
<i class="icon-home"></i>
<span>首页</span>
</div>
</div>
</template>
<script>
import bus from '../utils/bus'
export default {
methods: {
goToPage(route) {
this.$router.push(route.path);
bus.$emit('meta', route.meta);
}
}
}
</script>
复制代码
C.vue
<template>
<div class="top-nav">
<span class="title">{{title}}</span>
</div>
</template>
<script>
import bus from '../utils/bus'
export default {
data() {
return {
title: ''
}
},
created() {
bus.$on('meta', msg=> {
this.title = msg;
})
}
}
</script>
复制代码
EventEmitter
方法EventEmitter
方法主要包含了 on
,emit
,once
,off
方法。
class Event {
constructor() {
this.events = Object.create(null);
}
on(name, fn) {
if (!this.events[name]) {
this.events[name] = []
}
this.events[name].push(fn);
return this;
}
emit(name, ...args) {
if (!this.events[name]) {
return this;
}
const fns = this.events[name]
fns.forEach(fn => fn.call(this, ...args))
return this;
}
off(name,fn) {
if (!this.events[name]) {
return this;
}
if (!fn) {
this.events[name] = null
return this
}
const index = this.events[name].indexOf(fn);
this.events[name].splice(index, 1);
return this;
}
once(name,fn) {
const only = () => {
fn.apply(this, arguments);
this.off(name, only);
};
this.on(name, only);
return this;
}
}
复制代码
Vue
采用 数据劫持 结合 发布者-订阅者 模式的方式,经过 Object.defineProperty()
来劫持各个属性的 setter
以及getter
,在数据变更时发布消息给订阅者,触发相应的监听回调。
第一步:须要 Observe
的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter
和 getter
。这样的话,给这个对象的某个值赋值,就会触发setter
,那么就能监听到了数据变化。
第二步:Compile
解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每一个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变更,收到通知,更新数据。
第三步:Watcher
订阅者是Observer
和 Compile
之间通讯的桥梁,主要作的事情有:
属性订阅器(dep)
里面添加本身。update()
方法dep.notice()
通知时,能调用自身的update()
方法,并触发 Compile
中绑定的回调,则功成身退。第四步:MVVM
做为数据绑定的入口,整合 Observer
、Compile
和 Watcher
三者,经过 Observer
来监听本身的 model
数据变化,经过 Compile
来解析编译模板指令,最终利用 Watcher
搭起 Observer
和 Compile
之间的桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model 变动的双向绑定效果。
key
值的做用使用 v-for
更新已渲染的元素列表时,默认用就地复用策略。
列表数据修改的时候,他会根据key值去判断某个值是否修改:若是修改,则从新渲染这一项;不然复用以前的dom,仅修改value
值。
当数据发生改变时,set
方法会让调用Dep.notify
通知全部订阅者Watcher
,订阅者就会调用patch
给真实的DOM
打补丁,更新相应的视图。
diff流程
patch
函数接收两个参数oldVnode
和Vnode
分别表明新的节点和以前的旧节点
patchVnode
;Vnode
替换oldVnode
;patchVnode
:当咱们肯定两个节点值得比较以后咱们会对两个节点指定patchVnode
方法;
Vnode
和oldVnode
是否指向同一个对象,若是是,那么直接return
;updateChildren
函数比较子节点,这一步很重要;updateChildren函数图解
如今分别对oldS、oldE、S、E两两作sameVnode比较,有四种比较方式,当其中两个能匹配上那么真实dom中的相应节点会移到Vnode相应的位置,这句话有点绕,打个比方:
能够分红三部分
答案:
compile
编译器把template
编译成AST
语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile
是createCompiler
的返回值,createCompiler
是用以- 建立编译器的。另外compile
还负责合并option
。AST
会通过generate
(将AST语法树转化成render funtion字符串的过程)获得render
函数,render的返回值是VNode
,VNode是Vue的虚拟DOM节点,里面有(标签名、子节点、文本等等);computed
是计算一个新的属性,并将该属性挂载到 vm(Vue 实例)上,而 watch 是监听已经存在且已挂载到 vm 上的数据,因此用 watch
一样能够监听 computed 计算属性的变化(其它还有 data、props)
computed
本质是一个惰性求值的观察者,具备缓存性,只有当依赖变化后,第一次访问 computed 属性,才会计算新的值,而watch
则是当数据发生变化便会调用执行函数 从使用场景上说,computed 适用一个数据被多个数据影响,而 watch 适用一个数据影响多个数据;
vuex
就像一个全局的仓库,公共的状态或者复杂组件交互的状态咱们会抽离出来放进里面。
vuex的核心主要包括如下几个部分:
state
:state里面就是存放的咱们须要使用的状态,他是单向数据流,在 vue 中不容许直接对他进行修改,而是使用 mutations 去进行修改mutations
: mutations 就是存放如何更改状态的一些方法actions
: actions 是来作异步修改的,他能够等待异步结束后,再去使用 commit mutations 去修改状态getters
: 至关因而 state 的计算属性使用:
computed
中使用 this.$store.state
获得想要的状态this.$store.commit
方法去修改状态mapState,mapMutations
辅助函数指令都是行内属性
`v-model`放在input、textarea、select>option上的,实现双向数据绑定
`v-text` 展现对应的文本
`v-once` 对应的标签只渲染一次
`v-show=布尔` 是否能显示,true能显示,false不能显示(存在隐式转化)
`v-html` 把值中的标签渲染出来
复制代码
v-for
循环显示元素
能够循环数组、对象、数字、字符串
最好加:key='a+i'
v-for='item in ary'
复制代码
v-bind
用于绑定行内属性
简写成:
复制代码
v-if
控制是否渲染该元素
值是true,则渲染该元素;false则不渲染
与v-else v-else-if连着使用
可使用template标签,就不会出现多余标签
复制代码
基本用法
步骤
- 一、声明组件
- 二、编写路由映射表
- 三、把编辑好的映射表注入到
router
实例中- 四、把
router
实例注入到根实例中router-link
控制跳转的连接和显示的文字router-view
控制显示的组件内容active-class
控制选中对应路径的类名tag
控制渲染成什么标签
<body>
<div id="app">
<router-link to='/home' active-class='current'>首页</router-link>
<router-link to='/list' tag='div'>列表</router-link>
<router-view></router-view>
</div>
</body>
</html>
<template id="home">
<div>home</div>
</template>
<template id="list">
<div>list</div>
</template>
<script src="../node/node_modules/vue/dist/vue.js"></script>
<script src="../node_modules/vue-router/dist/vue-router.js"></script>
<script>
let home = {
template: '#home',
}
let list = {
template: '#list',
}
//路由映射表
let routes = [{
path: '/home',
component: home
},
{
path: '/list',
component: list
}
]
let router=new VueRouter({
routes:routes,
})
let vm = new Vue({
el: '#app',
data: {
name: "liu"
},
router,
})
</script>
复制代码
传参
提供了两种传参方式
- 一、
query
传参(问号传参) 路由映射表不用改动 :to={path:'',query:{}}或者:to={name:'',query:{}}
- 二、
params
传参(路径传参) 在映射表中添加 /:变量 的形式; :to={name:'',params:{变量:''}}}
<router-link :to='{path:"/list",query:{id:123,e:name}}' tag='div'>
列表</router-link>
重定向redirect
let routes = [
{
path:'/',
redirect:'/son2/222'
},
{
path:'/son1',
// redirect:'/son2/5555',
name:'son1',
component:son1,
redirect:'/son1/sz',
children:[
{
path:'/son1/sz',
component:sz
}
]
},
{
path:'/son2/:bl1234',
name:'son2',
component:son2
},
{
path:'/*',
redirect:'/son1'
}
]
复制代码
推荐文章 前端面试题—vue部分详解
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用
window.location.hash
读取; 特色:hash
虽然在URL
中,但不被包括在HTTP
请求中;用来指导浏览器动做,对服务端安全无用,hash
不会重加载页面。
hash 模式下,仅 hash 符号以前的内容会被包含在请求中,如
http://www.xxx.com
,所以对于后端来讲,即便没有作到对路由的全覆盖,也不会返回 404 错误。
history模式:
history
采用HTML5
的新特性;且提供了两个新方法:pushState()
,replaceState()
能够对浏览器历史记录栈进行修改,以及popState
事件的监听到状态变动。
history 模式下,前端的
URL
必须和实际向后端发起请求的URL
一致,如http://www.xxx.com/items/id
。后端若是缺乏对/items/id
的路由处理,将返回 404 错误。
vue
组件的过程?1)首先,组件能够提高整个项目的开发效率。可以把页面抽象成多个相对独立的模块,解决了咱们传统项目开发:效率低、难维护、复用性等问题。
2)使用Vue.extend
方法建立一个组件,而后使用Vue.component
方法注册组件。子组件须要数据,能够在props
中接受定义。而子组件修改好数据后,想把数据传递给父组件。能够采用emit
方法。
v-if
和v-show
的共同点和区别(考察频率:中)参考官方文档
v-if
是“真正”的条件渲染,由于它会确保在切换过程当中条件块内的事件监听器和子组件适当地被销毁和重建。v-if
也是惰性的:若是在初始渲染时条件为假,则什么也不作——直到条件第一次变为真时,才会开始渲染条件块。v-show
就简单得多——无论初始条件是什么,元素老是会被渲染,而且只是简单地基于 CSS 进行切换。v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。所以,若是须要很是频繁地切换,则使用 v-show
较好;若是在运行时条件不多改变,则使用 v-if
较好。Vue 在 render
中 createElement
的时候,并非产生真实的 DOM 元素,实际上 createElement
描述为 createNodeDescription
,由于它所包含的信息会告诉 Vue 页面上须要渲染什么样的节点。 所以,咱们将这样的节点描述为 “虚拟节点”(Virtual Node),简称 VNode。“虚拟 DOM” 是咱们对由 Vue 组件树创建的整个 VNode 树的称呼。
推荐:
一、体积小:
vue-resource
很是小巧,在压缩之后只有大约12KB,服务端启用gzip压缩后只有4.5KB大小,这远比jQuery
的体积要小得多。
二、支持主流浏览器:和
Vue.js
同样,vue-resource
除了不支持IE 9如下的浏览器,其余主流的浏览器都支持
三、支持
Promise API
和URI
Templates:Promise
是ES6
的特性,Promise
的中文含义为“先知”,Promise
对象用于异步计算。URI Templates
表示URI
模板,有些相似于ASP.NET MVC
的路由模板
四、支持拦截器:拦截器是全局的,拦截器能够在请求发送前和发送请求后作一些处理。 拦截器在一些场景下会很是有用,好比请求发送前在
headers
中设置access_token
,或者在请求失败时,提供共通的处理方式。
1).基于全局Vue对象
使用http
Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback);
Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
复制代码
2).在一个Vue实例
内使用$http
this.$http.get('/someUrl', [options]).then(successCallback, errorCallback);
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
复制代码
选项options
url
:发送请求的URL
body
:做为请求主体发送的数据
headers
:标题对象做为HTTP请求表头发送
params
:做为url参数发送的参数对象
$http
方式数据请求
- get
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/vue.resource/1.2.1/vue-resource.min.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="sendGet()">发送get请求</button>
</div>
</body>
</html>
<script>
var vm = new Vue({
el: "#app",
methods: {
sendGet: function() {
//这里的this指代的是 vm对象
var url = "http://127.0.0.1:3000/login?username=admin&password=123";
this.$http.get(url).then(function(res) {
console.log(res.data)
},function(err){
console.log(err)
})
}
}
})
</script>
复制代码
- post
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/vue.resource/1.2.1/vue-resource.min.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="sendPost()">发送post请求</button>
</div>
</body>
</html>
<script>
var vm = new Vue({
el: "#app",
methods: {
sendPost: function() {
//这里的this指代的是 vm对象
var url = "http://127.0.0.1:3000/postLogin";
/**
* vue的post参数:若是是普通的post请求,最后一个就是{emulateJSON:true}
*
* 参数一:url
*
* 参数二:data-要传递的数据-对象的形式
*
* 参数三:若是是普通的post请求,最后一个就是{emulateJSON:true}
*
* */
this.$http.post(url, {
username: 'lisi',
password: 'lisi'
}, {
emulateJSON: true
}).then(function(res) {
console.log(res.data)
})
}
}
})
</script>
复制代码
- jsonp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/vue.resource/1.2.1/vue-resource.min.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="sendPost()">发送post请求</button>
</div>
</body>
</html>
<script>
var vm = new Vue({
el: "#app",
methods: {
sendPost: function() {
//这里的this指代的是 vm对象
var url = "http://127.0.0.1:3000/postLogin";
/**
* vue的post参数:若是是普通的post请求,最后一个就是{emulateJSON:true}
*
* 参数一:url
*
* 参数二:data-要传递的数据-对象的形式
*
* 参数三:若是是普通的post请求,最后一个就是{emulateJSON:true}
*
* */
this.$http.post(url, {
username: 'lisi',
password: 'lisi'
}, {
emulateJSON: true
}).then(function(res) {
console.log(res.data)
})
}
}
})
</script>
复制代码
在Vue中发送AJAX请求:Vue自己并不支持发送ajax请求,须要使用第三方插件vue-resources(1.0,可是2.0中不建议使用)、官方推荐使用axis(2.0);可是也能够用jQuery;
axios是一个基于promise的http请求客户端,用来发送请求,也是vue2.0官方推荐使用的;在vue2.0官方推荐的,同时再也不对vue-resource进行更新和维护。
axios具体用来作什么
从浏览器中建立XMLHttpRequests
让HTTP从node.js的请求
支持Promise API
截取请求和响应
转换请求和响应数据
取消请求
自动转换JSON数据
客户端支持防范XSRF
axios的github地址和使用方式:github.com/axios/axios
axios([options])
axios.get(url[,options])
;
传参方式:
1.经过`url`传参
2.经过`params`选项传参
复制代码
axios.post(url,data,[options])
;
`axios`默认发送数据时,数据格式是`Request` `Payload`,并不是咱们经常使用的`Form Data`格式,
因此参数必需要以键值对形式传递,不能以`json`形式传参
传参方式:
1.本身拼接为键值对
2.使用`transformRequest`,在请求发送前将请求数据进行转换
3.若是使用模块化开发,可使用`qs`模块进行转换
复制代码
axios
自己并不支持发送跨域的请求,没有提供相应的API,因此只能使用第三方库
客户端经过jsonp或者vue-resource支持
若是服务端经过CORS支持跨域,则客户端不须要处理跨域
vue
,引入jQuery
(由于等下用Ajax请求数据用到jQuery)<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
复制代码
vue
首先在本身的网页body
内添加一个div
包括全部内容,并给这个div
设置id
如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
//你的html代码
</div>
</body>
</html>
复制代码
vue
并挂载到页面(若是在单首创建js
文件来写,则需在htmll中引入这个js文件)建立以下:
window.onload = function() {
new Vue({
el: "#app",//将vue挂载到html中你建立的那个带id="app"上
data: {
aboutData: [], //建一个空数组,用来保存调用接口获取的数据
},
created: function() {
this.getRoute();
},
mounted() {
},
methods: {
getRoute: function() {
var that = this;
$.ajax({
type: "GET",
url:
"填写你的数据接口地址",
dataType: "json",
success: function(response) {
aboutData = response;
//写在获取数据成功后你想进行的操做
},
error: function() {
alert("请求失败");
}
});
}
});
};
复制代码
html
代码中调用vue
相关语法来写进动态数据了微信小程序篇