vue数据响应原理
1:原理
原理图:
从MVVM模式
侵入式和非侵入式(react和小程序直接调用方法改变)
2:object.defineProperty()方法
let obj={
}
Object.defineProperty(obj,'name',{
value:'名字',
writable:true,//是否可写
enumerable:true, // 是否可枚举
configurable:true // 是否可以删除
})
Object.defineProperty(obj,'age',{
value:18,
writable:true,//是否可写
enumerable:true, // 是否可枚举【是否可以遍历这属性】
configurable:true // 是否可以删除
})
console.log(obj)
defineReactiveFun(){
let obj={sex:'男'}
function defineReactive (data,key,val){
Object.defineProperty(data,key,{
enumerable:true, // 是否可枚举(遍历到这属性)
configurable:true,
get(){
console.log('访问data属性',key)
return val;
},
set(newVal){
console.log('改变data属性',key,newVal)
val=newVal
}
})
}
new Promise(function(resolve,reject){
defineReactive(obj,'age',18)
resolve()
}).then(()=>{
obj.age++
console.log(obj)
console.log(obj.age) //19
})
},
3:响应式处理(对象)
defineProperty.vue
defineReactiveFun(){
var obj={
a:{
m:{
n:5
}
},
b:{
b1:'dsfdf'
}
}
console.log(obj)
observe(obj)
obj.a.m.n=6
},
Observe.js
// 创建observer 函数注意函数的没有r
export default function observe(value) {
if (typeof value != 'object') return;
var ob;
if (typeof value.__ob__ !== 'undefined') {
ob = value.__ob__
} else {
ob = new Observer(value)
}
return ob;
}
Observer.js
import defineReactive from '../vueReactive/defineReactive.js'
export default class Observer {
constructor(value) {
// 注意:下面的this 是构造函数的this。不是表示类的本身,而不是实例
def(value, '__obj__', this, false)
console.log('我是Observer构造器', value);
this.walk(value)
}
walk(value) {
for (let k in value) {
defineReactive(value, k)
}
}
}
function def(obj, key, value, enumerable) {
Object.defineProperty(obj, key, {
value,
enumerable,
writable: true,
configurable: true
})
}
defineReactive.js
import observe from '../vueReactive/Observe'
export default function defineReactive(data, key, val) {
console.log('我是defineReactive', key)
if (arguments.length == 2) {
val = data[key];
}
// 子元素要进行observe 至此形成递归,这个递归不是函数自己调用自己,而是多个函数,类循环调用
let childOb = observe(val)
Object.defineProperty(data, key, {
enumerable: true, // 是否可枚举(遍历到这属性)
configurable: true,
get() {
console.log('访问data属性', key)
return val;
},
set(newVal) {
console.log('改变data属性', key, newVal)
val = newVal
childOb = observe(newVal) // 设置了新值,这个新值也要被observe
}
})
}
3:响应式处理(数组)
一:什么是vue
1:构建用户界面
用vue 往html页面中填充数据
2:框架
vue 指令、组件(对复杂的ui结构复用)、路由、vuex
二:vue特性:数据驱动视图和双向数据绑定
1 数据驱动视图
2: 双向数据绑定
在网页中:from标题复制采集数据 ajax负责提交数据
三MVVM框架
1:结构
2:原理
3:代码与结构的关系
四:指令与过滤器
1:指令
A: 内容指令:v-html {{}} v-text
B: 属性指令:v-bind
<div :data-titke="属性指令"></div>
<img :src="srcStr"/>
C: 事件指令 v-on:click 或者@click
<button @click="count++">count is: {{ count }}</button>
$event
<button @click="clickFun(1,$event)">button</button>
clickFun(n,e){
console.log(e)
e.target.innerHTML='点击'
}
事件修饰符
prevent
<a href="www.baidu.com" @click.prevent="tiaoFun">跳转</a>
stop
<div @click="divFun1">
阻止冒泡1
<div @click.stop="divFun2">阻止冒泡2</div>
</div>
按键修饰符
按键修饰:<input @keyup="keyupFun">
D: 双向绑定指令 v-model
双向数据绑定修饰符
E: 条件渲染指令 v-if 和v-show
v-if 和v-else-if /v-else
<div v-if="n1">sdf</div>
<div v-else-if="n2">sdf</div>
<div v-else>sdf</div>
F: 列表渲染指令
2:过滤器【vue3.0已废除】
私有过滤器和全局过滤器
连续调用多个过滤器
五:侦听器
六:计算属性
**只要计算属性中;依赖的的数据源变化,则计算属性会自动重新求值:如:下面的 r g b
**
计算属性改造:
七:axios
结合 ansync、await/和解构赋值 代码美滋滋
八:组件
组件中的data为啥是个函数不是对象?
我们可以发现当我们使用组件的时候,虽然data是在构造器的原型链上被创建的,但是实例化的component1和component2确是共享同样的data对象,当你修改一个属性的时候,data也会发生改变,这明显不是我们想要的效果。
当我们的data是一个函数的时候,每一个实例的data属性都是独立的,不会相互影响了。你现在知道为什么vue组件的data必须是函数了吧
九 vscode中常用插件
1: @路径提示插件
打开vscode settings.json添加一下代码
"path-autocomplete.extensionOnImport":true,
"path-autocomplete.pathMappings": {
"@":"${folder}/src"
}
2:标签回阔自动生成
十:简写计较方法案例
累加
十一:注册组件
注册全局组件
注册私有子组件
十二:props 接受参数
1:props只读的,子组件不能改父组件传过来的的值
deep 父组件修改组件的样式
十三:vue 单应用页面渲染原理步骤
十三:vue 组件生命周期
阶段结构图
分析周期流程图
十四:兄弟组件数据共享eventBus.js
十五:ref使用
获取当前组件Dom
获取子组件,然后调用子组件的方法
this.$nextTick(cb)
十六:常见的数组方法(购物车)
some
every
reduce方法
十六:计算属性computed
十七: 动态组件component
十八:keep-alive
deactivated、activted
include 属性指定缓存组件
exclude 排除项;主要 不能和include同时使用
十九:组件的name
二十:插槽
二十一:自定义指令
私有
upadate(更新绑定的指定一的值)
优化简写更新
全局
二十二:main.js的提示
二十三:esline作用和 vscode工具格式化
二十四:路由
hash: location.hash
前端路由工作方式
模拟前端路由 window.onhashchange
vue-router官方插件
安装与使用
小细节注意:
在进行模块化导入的时候,如果给定文件夹,则默认导入这个文件夹下,名字叫做index.js文件
router文件夹的拓展
为了部署大项目,不要把所有的路由都放到index.js ,可以拆分多个js
router的占位符 router-view
路由重定向redirect
嵌套路由
动态路由 :注意获取的是$route 是不带r的
this.$route是路由的参数对象
this.$router是路由的导航对象
动态路由规则开启props传参
路径参数和查询参数 拓展:fullpath 和query
1:在hash地址中 /后面的参数项,叫做路径参数项,通过this.$route.params 获取参数
/home/1
2::在hash地址中 ?后面的参数项 叫做查询参数,通过this.$route.query 来获取参数
/home?id=1&sel=2
路由导航跳转方式
1:声明式导航
2:编程式导航 push replace go
1):go 的简写 router.forward()
Vue路由传参详解(params 与 query)
params 传参类似于网络请求中的 post 请求,params 传过去的参数不会显示在地址栏中(但是不能刷新)。params 只能配合 name 使用,如果提供了 path,params 会失效。
query 传参类似于网络请求中的 get 请求,query 传过去的参数会拼接在地址栏中(?name=xx)。query 较为灵活既可以配合 path 使用,也能配合 name 使用(亲测可用)。
//query方式
<router-link :to="{path: '/linkTo', query: {name:'ming', age: 18 }}">
<button>跳转</button>
</router-link>
//params方式
<router-link :to="{name: 'linkTo', params: {name:'ming', age: 18 }}">
<button>跳转</button>
</router-link>
// 以query方式接收参数:【query传递数据是通过URL传递的,类似ajax中的get方式】
console.log(this.$route.query.name); // ming
console.log(this.$route.query.age); // 18
// 以params方式接收参数:【params方式,类似ajax中的post方式】
console.log(this.$route.params.name); // ming
console.log(this.$route.params.age); // 18
//query方式
<button @click="jump1">跳转</button>
jump1() {
this.$router.push({
path: '/linkTo',
query: {
name: "ming",
age: 18
}
});
}
//⚠️注:如果要传递的参数很长时,请用params方式,因为query方式是通过URL传递的,而URL传参数长度是有限制的哦!!
//params方式
<button @click="jump2">跳转</button>
open2() {
this.$router.push({
name: "abolinkTout", // ⚠️注:这里不能用path路径,只能用name【请对照router.js中的路由规则中的name项】,否则取不到传过去的数据
params: {
name: "ming",
age: 18
}
});
}
//⚠️注:在传递参数时,用什么方式传参,就用什么方式接收!!
// 以query方式接收参数:【query传递数据是通过URL传递的,类似ajax中的get方式】
console.log(this.$route.query.name); // ming
console.log(this.$route.query.age); // 18
// 以params方式接收参数:【params方式,类似ajax中的post方式】
console.log(this.$route.params.name); // ming
console.log(this.$route.params.age); // 18
// this.$route 路由信息对象
console.log(this.$route);
监听路由参数的变化:商品详情页面点击切换商品
参考链接:
二十五:导航守卫
1:全局前置守卫 router.beforeEach()
守卫形参 to from next
next 3钟调用方式
2: 全局解析守卫router.beforeResolve 注册一个全局守卫
3:全局后置钩子 afterEach
这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {
// ...
})
4:路由独享的守卫
5: 组件内的守卫-
beforeRouteEnterbeforeRouteUpdate(2.2 新增)beforeRouteLeave
6:完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave守卫。 - 调用全局的
beforeEach守卫。 - 在重用的组件里调用
beforeRouteUpdate守卫 (2.2+)。 - 在路由配置里调用
beforeEnter。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter。 - 调用全局的
beforeResolve守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter守卫中传给next的回调函数,创建好的组件实例会作为回调函数的参数传
二十六: 路由元信息
二十七:Es6模块化
1:默认导入与导出
2 按需导入与导出
3:直接导入并执行
二十八pormise
第三方包读取文件 then-fs
npm install then-sf 按照第三包
按顺序执行
catch捕获错误
promise all 等待所有promise执行成功后执行
promise race 只要一个promise返回成功就执行
二十九:async 和await
a:基本用法
b:注意事项
三十 eventLoop
A: 同步任务和异步任务
Event Loop即事件循环,是指浏览器或Node的一种解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。
1:案例
B:宏任务和薇任务
案例1:
案例2
三十一:sass 和scss区别
1:异同:简言之可以理解scss是sass的一个升级版本,完全兼容sass之前的功能,又有了些新增能力。语法形式上有些许不同,最主要的就是sass是靠缩进表示嵌套关系,scss是花括号
2 scss功能很强大的样子,能做运算、写函数啥的,但是我只是作为语法糖用而已,只看了些基础功能