写在前面
相信进来的小伙伴都对vue有一定的了解或者使用,毕竟现在前端最火的框架之一,vue是最好学的和入门相对简单,毕竟是中文吧,亲切感倍增,鄙人呢,现在的工作用的主要框架也是vue,平时喜欢追根溯源,最近身边很多小伙伴去面试或者做面试官,反馈的某某大佬,写代码棒棒的,但在原理和使用场景方面不够透彻,所以在这里就总结一些大家平时不留意的点,从vue入门到源码小实现,写来旨在和大家一起交流。
从0开始
什么是vue?
vue(读音/u:/,类似于vew)是一套用于构建用户界面的渐进式框架。 特点:易用,灵活,高效 渐进式框架; 逐一递增vue+ components+vue-router+vuex+vue-cli
什么是库,什么是框架?
库是将代码集合成一个产品库是我们调用库中的方法实现自己的功能。(比如大家熟悉的jquery,就是库。) 框架则是为解决一类问题而开发的产品框架是我们在指定的位置编写好代码,框架帮我们调用。(vue、react、ng) 总而言之,框架是库的升级版 plus。
//...引入库等
let vm = new Vue({
el:'#app',
//template: '<h1>hello world</h1>',
data:{ // 存放数据
msg:'hello',
info:{xxx:'xxx'},
arr:[1,2,3,4]
}
});
vm.$nextTick(()=>{
console.log(vm.$el.innerHTML);
console.log(vm.$options);
});
vm.$watch('info.xxx',function(newValue,oldValue){
console.log(newValue,oldValue);
})
vue实例上的方法 vm.options nextTick 等等
当然你可以在控制台上面打印
mvvm
在传统的mvc中除了mode和vew以外的逻辑都放在了 controller中,导致 controller逻辑复杂难以维护,在mwm中vew和 mode没有直接的关系,全部通过 vIewMode进行交互
方便大家加深印象百度一张图片:
模板语法
允许开发者声明式地将DOM绑定至底层vue实例的数据。在使用数据前需要先声明 编写三元表达式 JavaScript表达式
<!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">
<!-- 取值表达式 可以 运算 , 取值 , 做三元 -->
{{1+1}}
{{msg}}
{{flag?'ok':'no'}}
{{ {name:1} }}
{{ 'msg' + 'hello'}}
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
data:{
msg:'hello',
flag:true
}
});
</script>
</body>
</html>
划重点-△观察数据变化
vue 数据劫持,必须要知道Object.defineProperty,以下是代码简单实现
// 数据源
let obj = {
name:'jw',
age: {
age:18
}
}
function observer(obj){
if(typeof obj == 'object'){
for(let key in obj){
defineReactive(obj,key,obj[key]);
}
}
}
function defineReactive(obj,key,value){
observer(value); // 判断value是不是一个对象 如果是对象 会继续监控
Object.defineProperty(obj,key,{
get(){
return value
},
set(val){
observer(val); // 如果设置的值是对象 需要在进行这个对象的监控
console.log('数据更新了')
value = val;
}
})
}
observer(obj);
obj.age = {name:1};
Object.defienProperty 不支持数组的,当然有童鞋就会问,那如果是数组呢,
// vue 把 这个数组上的所有方法 都重写了
let arr = ['push','slice','shifit','unshift']
arr.forEach(method=>{
let oldPush = Array.prototype[method];
Array.prototype[method] = function(value){
console.log('数据更新了')
oldPush.call(this,value);
}
})
obj.age.push(5);
obj.age.length--;
如果属性不存在 默认后增加的内容 并不会刷新视图
数组调用push 是无效的
vue指令 v-
在vue中 Directives)是带有v-前缀的特殊特性,主要的功能就是操作DOM, 多的不说,上代码说明
<div id="app">
<!-- 内部会进行缓存 以后使用的都是缓存里的结果 -->
<div v-once>{{msg}}</div>
<!-- v-html innerHTML XSS攻击 不能将用户输入的内容展现出来 内容必须是可信任的-->
<div v-html="d"></div>
<!-- v-if 如果不成里 dom就会消失 -->
<!-- v-if 控制的是 dom 有没有 v-show控制的是样式 -->
<!-- v-show不支持template -->
<template v-show="flag">
<div>hello</div>
<div >123</div>
</template>
<div>312</div>
</div>
v-for 记得写key,提高渲染效率,后面说的diff算法的时候会详细说,key可以用来区分元素,尽量不要使用index做为key 如果有唯一标示 尽量使用 唯一标示哦,有点需要注意的,就是template循环的时候key放在子元素上面,vue 2.5 以上要求 必须在循环时 使用key属性 。
<template v-for="i in 3" >
<div :key="i+'_1'" :a="i+'_1'">{{i}}</div>
<div :key="`${i}_2`" :a="`${i}_2`" a="{{i}}">{{i}}</div>
</template>
v-model 实现一个输入框双向绑定只需要
<input type="text" v-model="msg">
其实v-model 是 @input + :value 的一个语法糖
<input type="text" :value="msg" @input="e=>msg=e.target.value">
计算属性 computed
小面试题:
computed 和 method的区别
- computed有缓存,method没有
computed 和 watch 区别
- watch可以支持异步
- watch 可以实现一些简单的功能 先去想能不能用计算属性computed实现
<!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">
{{ fullName }}
{{msg}}
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
data:{
firstName:'大',
lastName:'飞',
msg:'hello',
fullName:''
},
// mounted(){ // 顺便说下,在不同的阶段会被调用 是钩子函数
// this.getFullName();
// },
methods:{
getFullName(){
this.fullName = this.firstName + this.lastName
}
},
watch:{ // vm.$watch('firstname',()=>{})
firstName:{
handler(newValue){
setTimeout(()=>{
this.getFullName();
},1000)
},
immediate:true // deep:true
},
lastName(){
this.getFullName();
}
},
computed:{ // Object.defineProperty来实现
fullName(){ // get方法,有缓存 如果值没有更改会从缓存中取值
return this.firstName + this.lastName
}
},
// methods:{
// getFullName(){
// console.log('哈哈')
// return this.firstName + this.lastName
// }
// }
})
</script>
</body>
</html>
computed用法深入一点点,相信大家平时都会有做多选框,大家的方法估计是都是用methods来实现,可以尝试用computed,代码更少更优雅。
<!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">
全选 <input type="checkbox" v-model="checkAll">
<input type="checkbox" v-for="(item,key) in checks" v-model="item.value" :key="key">
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
data:{
checks:[{value:true},{value:false},{value:true}],
},
computed:{
checkAll:{
get(){
return this.checks.every(check=>check.value)
},
set(value){ // 双向绑定数据
this.checks.forEach(check =>check.value = value);
}
}
}
})
</script>
</body>
</html>
今晚先写到这里,有空再继续更新自定义指令,生命周期,router、vuex,基本的坑点讲完后,我们再看看她们简单实现的小原理。感谢你,能够看到这里。 See you !