Runtime-Compiler/Runtime-only
如果在开发中,使用template,就需要选择Runtime-Compiler
如果在开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only
runtime-compiler: template -> ast ->render -> v-dom -> dom
runtime-only: render -> v-dom -> dom
ast: abstract syntax tree
在传统编译语言的流程中, 程序中的一段源代码在执行之前会经历三个步骤, 统称为“编
译”。
• 分词/词法分析(Tokenizing/Lexing)
这个过程会将由字符组成的字符串分解成(对编程语言来说) 有意义的代码块, 这些代
码块被称为词法单元(token)。 例如, 考虑程序 var a = 2;。 这段程序通常会被分解成
为下面这些词法单元: var、 a、 =、 2 、 ;。 空格是否会被当作词法单元, 取决于空格在
这门语言中是否具有意义。
分词(tokenizing) 和词法分析(Lexing) 之间的区别是非常微妙、 晦涩的,
主要差异在于词法单元的识别是通过有状态还是无状态的方式进行的。 简
单来说, 如果词法单元生成器在判断 a 是一个独立的词法单元还是其他词法
单元的一部分时, 调用的是有状态的解析规则, 那么这个过程就被称为词法
分析
• 解析/语法分析(Parsing)
这个过程是将词法单元流(数组) 转换成一个由元素逐级嵌套所组成的代表了程序语法
结构的树。 这个树被称为“抽象语法树”(Abstract Syntax Tree, AST)。
var a = 2; 的抽象语法树中可能会有一个叫作 VariableDeclaration 的顶级节点, 接下
来是一个叫作 Identifier(它的值是 a) 的子节点, 以及一个叫作 AssignmentExpression
的子节点。 AssignmentExpression 节点有一个叫作 NumericLiteral( 它的值是 2) 的子
节点。
• 代码生成
将 AST 转换为可执行代码的过程称被称为代码生成。 这个过程与语言、 目标平台等息
息相关。
抛开具体细节, 简单来说就是有某种方法可以将 var a = 2; 的 AST 转化为一组机器指
令, 用来创建一个叫作 a 的变量(包括分配内存等), 并将一个值储存在 a 中。
关于引擎如何管理系统资源超出了我们的讨论范围, 因此只需要简单地了解
引擎可以根据需要创建并储存变量即可。
比起那些编译过程只有三个步骤的语言的编译器, JavaScript 引擎要复杂得多。 例如, 在
语法分析和代码生成阶段有特定的步骤来对运行性能进行优化, 包括对冗余元素进行优化
等。
官方解释:
$nextTick 这是一个生命周期钩子 this.$nextTick(回调函数)在下一次DOM更新结束后执行其指定的回调 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行
<template>
<li>
<label>
<input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)"/>
<!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props -->
<!-- <input type="checkbox" v-model="todo.done"/> -->
<span v-show="!todo.isEdit">{{todo.title}}</span>
<input
type="text"
v-show="todo.isEdit"
:value="todo.title"
@blur="handleBlur(todo,$event)"
ref="inputTitle"
>
</label>
<button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
<button v-show="!todo.isEdit" class="btn btn-edit" @click="handleEdit(todo)">编辑</button>
</li>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name:'MyItem',
//声明接收todo
props:['todo'],
methods: {
//勾选or取消勾选
handleCheck(id){
//通知App组件将对应的todo对象的done值取反
// this.checkTodo(id)
this.$bus.$emit('checkTodo',id)
},
//删除
handleDelete(id){
if(confirm('确定删除吗?')){
//通知App组件将对应的todo对象删除
// this.deleteTodo(id)
// this.$bus.$emit('deleteTodo',id)
pubsub.publish('deleteTodo',id)
}
},
//编辑
handleEdit(todo){
if(todo.hasOwnProperty('isEdit')){
todo.isEdit = true
}else{
// console.log('@')
this.$set(todo,'isEdit',true)
}
this.$nextTick(function(){
this.$refs.inputTitle.focus()
})
},
//失去焦点回调(真正执行修改逻辑)
handleBlur(todo,e){
todo.isEdit = false
if(!e.target.value.trim()) return alert('输入不能为空!')
this.$bus.$emit('updateTodo',todo.id,e.target.value)
}
},
}
</script>
<style scoped>
/*item*/
li {
list-style: none;
height: 36px;
line-height: 36px;
padding: 0 5px;
border-bottom: 1px solid #ddd;
}
li label {
float: left;
cursor: pointer;
}
li label li input {
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
li button {
float: right;
display: none;
margin-top: 3px;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
li:hover{
background-color: #ddd;
}
li:hover button{
display: block;
}
</style>
activated和deactivated是路由组件所独有的两个钩子,用于捕获路由组件的激活状态
具体使用
activated路由组件被激活时触发
deactivated路由组件失活时触发
<template>
<ul>
<li :style="{opacity}">欢迎学习Vue</li>
<li>news001 <input type="text"></li>
<li>news002 <input type="text"></li>
<li>news003 <input type="text"></li>
</ul>
</template>
<script>
export default {
name:'News',
data() {
return {
opacity:1
}
},
/* beforeDestroy() {
console.log('News组件即将被销毁了')
clearInterval(this.timer)
}, */
/* mounted(){
this.timer = setInterval(() => {
console.log('@')
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
}, */
activated() {
console.log('News组件被激活了')
this.timer = setInterval(() => {
console.log('@')
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
},
deactivated() {
console.log('News组件失活了')
clearInterval(this.timer)
},
}
</script>
MVVM模型
M:模型 Model,data中的数据
V:视图 View,模板代码 V
M:视图模型 ViewModel,Vue实例
观察发现
data中所有的属性,最后都出现在了vm身上
vm身上所有的属性 及Vue原型身上所有的属性,在 Vue模板中都可以直接使用
数据代理
Vue中的数据代理通过vm对象来代理data对象中属性的操作(读/写)。 Vue中数据代理的好处:更加方便的操作data中的数据。
基本原理
通过object.defineProperty()把data对象中所有属性添加到vm上 为每一个添加到vm上的属性,都指定一个 gettersetter 在gettersetter内部去操作(读/写)data中对应的属性。
Vue将data中的数据拷贝了一份到_data属性中,又将_data里面的属性提到Vue实例中(如name),通过defineProperty实现数据代理,这样通过geter/setter操作 name,进而操作_data中的 name。而_data又对data进行数据劫持,实现响应式。
key 的作用与原理
reactvue中的key有什么作用?
1.(key的内部原理) 虚拟DOM中key的作用:key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后Vue进行新虚拟DOM与旧虚拟DOM的差异比较,比较规则如下
2.对比规则
2.1 旧虚拟DOM中找到了与新虚拟DOM相同的key
若虚拟DOM中内容没变, 直接使用之前的真实DOM
若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM 旧虚拟 2.2 DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
3.用index作为key可能会引发的问题 若对数据进行逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低 若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。
4.开发中如何选择key? 最好使用每条数据的唯一标识作为key,比如 id、手机号、身份证号、学号等唯一值 如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的 。
重要的内置关系
一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
为什么要有这个关系:让组件实例对象vc可以访问到 Vue原型上的属性、方法
Vuex 是什么
概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信.