Open lulujianglab opened 5 years ago
前段时间一直在用 react 写项目,最近的新项目想用vue 来写,发现大多数属性已经有点混淆了,于是花点时间重新梳理了下~
react
vue
配合对应的 vue-demo 看更容易理解哦
在讲vue 之前,我们先提一下框架和库的区别
库 — 类似于jQuery 这样的库,是操作 DOM 元素,发起ajax 请求等,中间还会用到一些其他的库,用来做模板引擎
jQuery
DOM
ajax
框架 — 全方位功能齐全,请求获取数据,模板渲染,框架就是一个简易的 DOM 操作 + 发请求 + 模板引擎 + 路由功能
所以,框架就是更为全面的功能,库就是单一的层面
从代码层面上讲,一般使用库的代码,是调用某个函数,我们自己把控库的代码;而使用框架,是框架在帮我们运行我们编写好的代码
比如,框架运行时,一般会初始化自身的代码,然后执行你所编写的代码,最后释放一些资源,其中初始化代码和释放资源都是框架自身的功能
作为框架来讲,基本是大而全,而库就比较专一
从运行层面上讲,对于框架来说,是我们把代码给框架运行,库是我们调用库
可以用于页面中简单粗暴的调试
注意:必须在 data 这个函数中返回的对象中声明
data
angular
ng-xxx
v-xxx
*v-text 元素的innerText 属性必须是双标签,只能用在双标签中,本质就是给元素的 innerText 赋值
v-text
innerText
v-html
innerHTML
v-if
v-else-if
v-else
<!---->
v-show
style
display:none
注意, v-if 如果值为 false,会留下一个 <!----> 作为标记,万一未来v-if 的值是 true 了,就是这里插入元素,如果有if 和else 就不需要单独留坑了
false
true
if
else
语法:在元素上 v-bind:原属性名="变量||变量名"
v-bind:原属性名="变量||变量名"
简写形式 :属性名=“变量名”
:属性名=“变量名”
click
v-on:原生事件名=“给变量进行操作||函数名”
@原生事件名=“给变量进行操作”
value 的值是根据 value 内部的变量,点击按钮,改变了 vue 内部的变量,vue 察觉到页面中使用的变量更改了,所以重新渲染了视图的更改部分
*input 输入框中的 value 属性改变,显示就改变
input
value
.value = myValue = 'abc'
v-bind
同时,当用户的输入值发生改变时,vue 就知道了让页面中凸显一个元素出来。页面的改变,影响 vue
这就是双向数据绑定(流),v-model="myValue",当元素的 value 值改变以后,就会给 vue 中的属性赋值
v-model="myValue"
v-bind 可以给任何属性赋值,是从 vue 到页面的单向数据流 v-model 只能给具备 value 属性的元素进行双向数据绑定(必须使用的是有 value 属性的元素)
v-model
双向数据绑定
input v-model="name"
input :value="name"
v-model: 其的改变影响其他v-bind:其的改变不影响其他
v-bind:
v-bind就是对属性的简单赋值,当内存中值改变,还是会触发重新渲染
v-for="item in arr"
v-for="item in obj"
v-for="(item,index) in arr" :class="index"
v-for
item
index
key
methods
this
this.xxx
this.xxxMethod
var Header = { template: '模板', data是一个函数,methods: 功能,components:子组件们}
components: {组件名: 组件对象}
<组件名></组件名>
template
小补充:常量传递直接用,变量传递加冒号
Vue.component('组件名',组件对象)
filter:{过滤器名: 过滤器fn}
{{原有数据|过滤器名}}
label
fn
function(data,argv1,argv2...){}
watch
computed
计算属性的名称
slot
<子组件>DOM</子组件>
props
实质上,slot 其实就是父组件传递给 DOM 结构
vue提供的内置组件 <slot></slot>
<slot></slot>
<my-li> <button>111</button> </my-li>
Vue 实例从创建到销毁的过程,就是生命周期
详细来说也就是从开始创建、初始化数据、编译模板、挂载 Dom、渲染→更新→渲染、卸载等一系列过程
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
在 beforeCreate 和 created 钩子函数之间的生命周期
进行初始化事件,进行数据的观测,在 created 的时候数据已经和 data 属性进行绑定 需要注意的是,此时还是没有 el 选项
el
created 钩子函数和 beforeMount 间的生命周期
首先会判断对象是否有 el 选项。如果有的话就继续向下编译,如果没有el选项,则停止编译,也就意味着停止了生命周期,直到在该 vue 实例上调用 vm.$mount(el)
vm.$mount(el)
如果 vue 实例对象中有 template 参数选项,则将其作为模板编译成 render 函数,如果没有 template 选项,则将外部 HTML 作为模板编译 template 中的模板优先级要高于 outer HTML 的优先级
render
outer HTML
render 函数选项 > template 选项 > outer HTML.
beforeMount 和 mounted 钩子函数间的生命周期
给 vue 实例对象添加 $el 成员,并且替换掉挂在的 DOM 元素
$el
注意,beforeMount 方法中 $el 还未被创建,这期间 VUE 先后生成两份模板,但是在 beforeMount 之前只是虚拟的,并未真实存在
id="app" 中的内容发生了变化
id="app"
beforeUpdate 钩子函数和updated 钩子函数间的生命周期
当 vue 发现 data 中的数据发生了改变,会触发对应组件的重新渲染,先后调用 beforeUpdate 和 updated 钩子函数
在 beforeUpdate 时,可以监听到 data 的变化但是 view 层没有被重新渲染,view 层的数据没有变化。等到 updated 的时候 view 层才被重新渲染,数据更新
需要注意的是,这里运行 console.log,在 beforeUpdated 钩子函数执行的时候里面的 DOM 元素就已经发生了变化,是因为还有 virtual DOM 这一层,实际上,我们打印 document.body.innerHTML,view 层是没有被重新渲染的
console.log
beforeUpdated
virtual DOM
document.body.innerHTML
beforeDestroy 和 destroyed 钩子函数间的生命周期
beforeDestroy 钩子函数在实例销毁之前调用 destroyed 钩子函数在 Vue 实例销毁后调用
需要注意的是,频繁的销毁和创建组件会影响页面性能,如果需要频繁的操作,我们可以使用 <keep-alive></keep-alive> 内置组件来控制组件的激活和停用,用法也就是包裹住需要销毁的组件的就好了
<keep-alive></keep-alive>
<keep-alive> <test v-if="isExist"></test> </keep-alive>
这个时候就用到了另一对钩子函数 activated 和 deactivated ,分别在组件被激活和被停用时触发
activated
deactivated
救命稻草,document.querySelector
document.querySelector
ref = "xxx"
this.$refs.xxx
ref 在 DOM 上获取的是原生 DOM 对象
ref
ref 在组件上获取的是组件对象
Vue.nextTick
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
需要了解的是 Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新
简单来说,Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新
//改变数据 `vm.message = 'changed'` //想要立即使用更新后的 DOM。这样不行,因为设置 message 后 DOM 还没有更新 `console.log(vm.$el.textContent)` // 并不会得到 'changed' //这样可以,`nextTick` 里面的代码会在 DOM 更新后执行,有一定的延时 Vue.nextTick(function(){ console.log(vm.$el.textContent) //可以得到 'changed' })
需要注意的是,在 created 和 mounted 阶段,如果需要操作渲染后的视图,要使用 nextTick 方法 比如刷新页面时在 mouted 事件中触发 input 元素的插入,并给 input 元素获取焦点
nextTick
mouted
var App = { template: `<div> <input type="text" v-if="isShow" ref="input" /> </div>`, data() { return { isShow: false } }, mounted() { // 显示元素,并给与获取焦点 this.isShow = true // 会触发 input 元素的插入,但这里并不会立马更新 DOM,最终代码更新完毕以后,vue才会根据实际的值,进行 DOM 的操作 // 我们希望在 vue 真正渲染 DOM 到页面以后,才操作如下事件 this.$nextTick(() => { this.$refs.input.focus() }) }, }
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
vm.$nextTick
mounted: function () { this.$nextTick(function () { // Code that will run only after the // entire view has been rendered }) }
single page application
Vue
{ name: 'home', path: '/home', component: Home}
router-link
to
<router-link :to="{name: 'home'}"></router-link>
path
href
大大降低维护成本,锚点值改变只用 main.js 中改变 path 属性即可
vue-router
router-link to="/xxx"
name
:to="{name:"xxx"}"
$router
配置 :to="{ name:'login', query:{id:1}} ,获取 this.$route.query.id,生成 <a href="/detail?id=1">
:to="{ name:'login', query:{id:1}}
this.$route.query.id
<a href="/detail?id=1">
配置 :to="{ name:'register', params:{name:'abc'},获取 this.$route.params.id,生成 <a href="/detail/abc">
:to="{ name:'register', params:{name:'abc'}
this.$route.params.id
<a href="/detail/abc">
router-view
meta
{ meta:{isChecked: true} }
router.beforeEach(function(to,from,next){ })
this.$router.push({name: 'xxx',query:{id:1},params:{name:'abc'} })
{name:'xxx',path:'/xxx/:name'}
根据历史记录,前进或后退
this.$router.go(-1|1)
本质是锚点值的变化
这里极度推荐使用 axios 发请求,可以看下 axios 的中文文档
axios
浏览器端发起 XMLHttpRequests 请求 node 端发起 http 请求 支持 Promise API 拦截请求和返回 转化请求和返回(数据) 取消请求 自动转化 json 数据 客户端支持抵御 XSRF(跨站请求伪造)
XMLHttpRequests
node
http
Promise API
json
XSRF
不像 jquery 那样嵌套,而是用 promise 只做 ajax 请求,不做其他的 DOM 之类的请求
jquery
promise
前段时间一直在用
react
写项目,最近的新项目想用vue
来写,发现大多数属性已经有点混淆了,于是花点时间重新梳理了下~配合对应的 vue-demo 看更容易理解哦
vue 基础
在讲
vue
之前,我们先提一下框架和库的区别库 — 类似于
jQuery
这样的库,是操作DOM
元素,发起ajax
请求等,中间还会用到一些其他的库,用来做模板引擎框架 — 全方位功能齐全,请求获取数据,模板渲染,框架就是一个简易的
DOM
操作 + 发请求 + 模板引擎 + 路由功能所以,框架就是更为全面的功能,库就是单一的层面
从代码层面上讲,一般使用库的代码,是调用某个函数,我们自己把控库的代码;而使用框架,是框架在帮我们运行我们编写好的代码
比如,框架运行时,一般会初始化自身的代码,然后执行你所编写的代码,最后释放一些资源,其中初始化代码和释放资源都是框架自身的功能
作为框架来讲,基本是大而全,而库就比较专一
从运行层面上讲,对于框架来说,是我们把代码给框架运行,库是我们调用库
插值表达式
可以用于页面中简单粗暴的调试
注意:必须在
data
这个函数中返回的对象中声明什么是指令
angular
中以ng-xxx
开头的就叫做指令vue
中以v-xxx
开头的就叫做指令DOM
行为,提供不同的功能,框架会进行相关DOM
操作的绑定vue 中常见的 v- 指令演示
*
v-text
元素的innerText
属性必须是双标签,只能用在双标签中,本质就是给元素的innerText
赋值v-html
元素的innerHTML
,本质就是给元素的innerHTML
赋值v-if
判断是否插入这个元素v-else-if
*v-else
移出和插入的问题,移出后是<!---->
v-show
隐藏元素,如果确定隐藏,会给元素的style
加上display:none
,本质是隐藏与否的问题注意,
v-if
如果值为false
,会留下一个<!---->
作为标记,万一未来v-if
的值是true
了,就是这里插入元素,如果有if
和else
就不需要单独留坑了v-bind 使用
语法:在元素上
v-bind:原属性名="变量||变量名"
简写形式
:属性名=“变量名”
v-on 的使用
click
并让使用变量的样式改变v-on:原生事件名=“给变量进行操作||函数名”
@原生事件名=“给变量进行操作”
value 的值是根据 value 内部的变量,点击按钮,改变了 vue 内部的变量,vue 察觉到页面中使用的变量更改了,所以重新渲染了视图的更改部分
小结:
*
input
输入框中的value
属性改变,显示就改变input
元素.value = myValue = 'abc'
v-bind
单向的功能同时,当用户的输入值发生改变时,vue 就知道了让页面中凸显一个元素出来。页面的改变,影响 vue
这就是双向数据绑定(流),
v-model="myValue"
,当元素的value
值改变以后,就会给 vue 中的属性赋值v-bind
可以给任何属性赋值,是从 vue 到页面的单向数据流v-model
只能给具备 value 属性的元素进行双向数据绑定(必须使用的是有 value 属性的元素)v-model
双向数据绑定
v-bind 和 v-model 的区别
input v-model="name"
input :value="name"
v-model
: 其的改变影响其他v-bind:
其的改变不影响其他v-bind
就是对属性的简单赋值,当内存中值改变,还是会触发重新渲染v-for 的使用
v-for="item in arr"
v-for="item in obj"
v-for="(item,index) in arr" :class="index"
v-for
的属性顺序 数组item
,index
对象value
,key
,index
关于对象内的 this
vue
已经把以前 this 是 window 或者事件对象的问题搞定了methods
和data
本身是在同一个对象中的,所以在该对象中可以通过this
随意取this.xxx
取data
中的值,this.xxxMethod
调methods
中的方法渲染组件-父使用子组件
var Header = { template: '模板', data是一个函数,methods: 功能,components:子组件们}
components: {组件名: 组件对象}
<组件名></组件名>
注意:在不同框架中,有的不支持大写字母,用的时候父子组件传值(父传子)
template
中直接用小补充:常量传递直接用,变量传递加冒号
注册全局组件
Vue.component('组件名',组件对象)
附加功能:过滤器&监视改动
filter:{过滤器名: 过滤器fn}
,最终 fn 内通过 return 产出最终的数据{{原有数据|过滤器名}}
input
框输入字符串,反字符串输出,按参数显示label
(中英文)fn
function(data,argv1,argv2...){}
watch
监视单个computed
监视多个 *computed
: {监视的业务名: function(){ return 显示的一些内容 }}计算属性的名称
slot( 传递 DOM )
slot
就是子组件里给DOM留下的坑<子组件>DOM</子组件>
slot
动态的 DOM,props
是动态的数据实质上,slot 其实就是父组件传递给 DOM 结构
vue提供的内置组件
<slot></slot>
生命周期函数(钩子函数)
Vue 实例从创建到销毁的过程,就是生命周期
详细来说也就是从开始创建、初始化数据、编译模板、挂载 Dom、渲染→更新→渲染、卸载等一系列过程
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
在
beforeCreate
和created
钩子函数之间的生命周期进行初始化事件,进行数据的观测,在
created
的时候数据已经和 data 属性进行绑定 需要注意的是,此时还是没有el
选项created
钩子函数和beforeMount
间的生命周期首先会判断对象是否有
el
选项。如果有的话就继续向下编译,如果没有el
选项,则停止编译,也就意味着停止了生命周期,直到在该 vue 实例上调用vm.$mount(el)
如果 vue 实例对象中有
template
参数选项,则将其作为模板编译成render
函数,如果没有template
选项,则将外部 HTML 作为模板编译template
中的模板优先级要高于outer HTML
的优先级render
函数选项 >template
选项 >outer HTML
.beforeMount
和mounted
钩子函数间的生命周期给 vue 实例对象添加
$el
成员,并且替换掉挂在的 DOM 元素注意,
beforeMount
方法中$el
还未被创建,这期间 VUE 先后生成两份模板,但是在beforeMount
之前只是虚拟的,并未真实存在mounted
id="app"
中的内容发生了变化beforeUpdate
钩子函数和updated
钩子函数间的生命周期当 vue 发现 data 中的数据发生了改变,会触发对应组件的重新渲染,先后调用
beforeUpdate
和updated
钩子函数在
beforeUpdate
时,可以监听到 data 的变化但是 view 层没有被重新渲染,view 层的数据没有变化。等到updated
的时候 view 层才被重新渲染,数据更新需要注意的是,这里运行
console.log
,在beforeUpdated
钩子函数执行的时候里面的 DOM 元素就已经发生了变化,是因为还有virtual DOM
这一层,实际上,我们打印document.body.innerHTML
,view 层是没有被重新渲染的beforeDestroy
和destroyed
钩子函数间的生命周期beforeDestroy
钩子函数在实例销毁之前调用destroyed
钩子函数在 Vue 实例销毁后调用需要注意的是,频繁的销毁和创建组件会影响页面性能,如果需要频繁的操作,我们可以使用
<keep-alive></keep-alive>
内置组件来控制组件的激活和停用,用法也就是包裹住需要销毁的组件的就好了这个时候就用到了另一对钩子函数
activated
和deactivated
,分别在组件被激活和被停用时触发获取 DOM 元素
救命稻草,
document.querySelector
template
中标识元素ref = "xxx"
this.$refs.xxx
获取元素ref
在 DOM 上获取的是原生 DOM 对象ref
在组件上获取的是组件对象$el
是拿起 DOMVue.nextTick
对异步函数的结果进行操作需要了解的是 Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新
简单来说,Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新
需要注意的是,在
created
和mounted
阶段,如果需要操作渲染后的视图,要使用nextTick
方法 比如刷新页面时在mouted
事件中触发 input 元素的插入,并给 input 元素获取焦点路由
路由原理
SPA
single page application
( 单页应用程序 )Vue
/angular
/react
命名路由
{ name: 'home', path: '/home', component: Home}
router-link
的to
属性中描述这个规则<router-link :to="{name: 'home'}"></router-link>
path
,生成自己的href
大大降低维护成本,锚点值改变只用 main.js 中改变 path 属性即可
小结
vue-router
使用步骤:1.引入 2.安装插件 3.创建路由实例 4.配置路由规则 5.将路由对象关联 vue 6.留坑router-link to="/xxx"
命名路由name
属性router-link
中:to="{name:"xxx"}"
vue-router 中的对象
$router
路由信息对象,只读对象$router
路由操作对象,只写对象配置
:to="{ name:'login', query:{id:1}}
,获取this.$route.query.id
,生成<a href="/detail?id=1">
配置
:to="{ name:'register', params:{name:'abc'}
,获取this.$route.params.id
,生成<a href="/detail/abc">
嵌套路由
router-view
的部分router-view
第一层中,包含一个router-view
知识点介绍
meta
元数据 =>meta
是对于路由规则是否需要验证权限的配置name
属性同级{ meta:{isChecked: true} }
router-view
之前router.beforeEach(function(to,from,next){ })
编程导航
this.$router.push({name: 'xxx',query:{id:1},params:{name:'abc'} })
{name:'xxx',path:'/xxx/:name'}
根据历史记录,前进或后退
this.$router.go(-1|1)
本质是锚点值的变化
axios
这里极度推荐使用
axios
发请求,可以看下axios
的中文文档不像
jquery
那样嵌套,而是用promise
只做ajax
请求,不做其他的 DOM 之类的请求