Vue2总结
Vue Devtools
Vue.js的基本了解
Vue基本简单语法
Vue组件
生命周期函数
计算属性和侦听器
修饰符
自定义事件
过渡动画
混入
自定义指令
插件
过滤器
Vue Devtools是一个浏览器插件,可以让你更好的调试Vue应用。但是当我打开B站的个人中心时,Vue Devtools插件亮起了,但是在控制台却没办法打开Vue Devtools。因为Vue Devtools是否开启,取决于Vue.config.devtools,如果设置Vue.config.devtools = false,则不开启Vue Devtools,设置Vue.config.devtools = true,则开启Vue Devtools。
可以下载并使用script引入
可以使用CDN的形式
可以npm
npm install vue
命令行工具-CLI
官方提供了Vue CLI来创建Vue项目的脚手架,脚手架的基本创建如下:
npm install -g @vue/cli 安装
vue create vue_text 创建脚手架
vue inspect > output.js(建议不使用) 生成默认配置文件,这里生成的时Vue CLI脚手架默认配置文件,如果你的脚手架创建的路径有中文的话,生成的output.js里面会出现乱码的现象。output.js文件最好不要生成,如果不小心改了里面的代码,就可能使项目启动不起来,如果想要改配置可以在根目录下创建一个vue.config.js文件。
开发版本
如果你使用的是github上的vue这里就有个小坑,github仓库里面的/dist文件夹可能不存在,需要你自己创建。
git clone https://github.com/vuejs/vue.git node_modules/vue
cd node_modules/vue
npm install
npm install -g bower//全局安装bower
bower help//可以查看bower是否安装成功
bower init//初始化一个json文件,用来保存项目的配置
bower install jquery --save//下载最新的jquery
bower info jquery//显示jquery包的信息
bower search bootstrap//搜索bootstrap包
bower uninstall jquery//卸载jquery包
在找bower资料的时候了解了npm和bower的区别和其他的一些东西。
模板语法-插值
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
- 使用v-once指令这个值将不会改变
这个值将不会改变: {{ message }}
- 使用v-html指令
- v-bind指令为标签绑定属性
-
模板语法-指令(v-on和v-bind存在缩写)
-
v-bind指令为标签绑定属性,例:id,class,url,src……(v-bind:url=“url”)
- 缩写:href=“url”/:[key]=“url”
- 动态参数v-bind:[urls]=“url”
-
v-on指令监听事件(v-on:click=“click”)(@click=“click”)
- 缩写@click=“click”/@[event]=“click”
- 动态参数v-on:[click]=“click”
var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
- 有时候需要访问原始的DOM事件,可以用特殊变量$event把它传入方法。
```
```
-
v-model实现表单输入和应用状态之间的双向绑定
-
※动态参数注意事项
- 在 DOM 中使用模板时 (直接在一个 HTML 文件里撰写模板),还需要避免使用大写字符来命名键名,因为浏览器会把 attribute 名全部强制转为小写
-
条件渲染
- v-if
- v-else
- v-if-else
- v-show:与v-if不同的是v-show的DOM还是保留在页面中的,只是通过切换css的display来使元素隐藏和显示
- ※注意:v-show 不支持 元素,也不支持 v-else。
-
列表渲染
- v-for
Vue组件
子父组件之间的相互传值
- 父组件
- 子组件
生命周期函数
初始化阶段
初始化阶段流程
- new Vue(),Vue实例
- init Events & Lifecycle 初始化生命周期函数和事件
- beforeCreate - beforeCreate()生命周期函数执行
- Init injections&reactivity - Vue内部添加data和methods等
- created - created()生命周期函数执行
- Has el option? – 是否有el选项 – 检查要挂到哪里
- 没有el,调用$mount()方法有,继续检查template选项
- 有el,检查template选项
beforeCreate(初始化界面前)
created(初始化界面后)
挂载阶段
挂载阶段流程
- template选项检查
- 有,编译template返回render渲染函数
- 无,编译el选项对应标签作为template(要渲染的模板)
- 虚拟DOM挂载成真实DOM之前
- beforeMount - beforeMount()生命周期函数被执行
- 把虚拟DOM和渲染的数据一并挂到真实DOM上
- 真实DOM挂载完毕
- mounted - mounted()生命周期钩子函数被执行
beforeMount(渲染DOM前)
mounted(渲染DOM后)
更新阶段
更新阶段流程
- 当data里数据改变, 更新DOM之前
- beforeUpdate - beforeUpdate()生命周期函数被执行
- 虚拟DOM重新渲染, 打补丁到真实DOM
- updated - updated()生命周期钩子函数被执行
beforeUpdate(更新数据前)
updated(更新数据后)
销毁阶段
销毁阶段流程
- $destroy()被调用 - 组件DOM被移除(例v-if)
- beforeDestroy - beforeDestroy()生命周期函数被执行
- 拆卸数据监视器、子组件和事件侦听器
- 实例销毁后, 最后触发一个钩子函数
- destroyed - destroyed()生命周期钩子函数被执行
beforeDestroy(卸载组件前)
destroyed(卸载组件后)
计算属性和侦听器
计算属性(computed)
Original message: "{{ message }}"
Computed reversed message: "{{ reversedMessage }}"
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
})
这里我当时觉得,在methods中定义函数,也可以实现相同的效果,但是我看Vue官网上介绍了计算属性和在methods定义方法的不同之处是计算属性是基于它们的响应式依赖进行缓存的只在相关响应式依赖发生改变时它们才会重新求值。这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:
computed: {
now: function () {
return Date.now()
}
}
相比之下,每次调用方法总会再次执行函数。
侦听器(watch)
Original message: "{{ message }}"
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
watch:{
message(){
//当this.message中的数据变化是,执行这里面的代码。
}
}
})
这里我一直有一点疑问的地方,如果data中的数据为msg:{message:‘Hellow’}或者data中的数据为数组时,在watch中怎么写才能监听message的变化呢?以下资料来源
- watch监听数组元素
//第一种方法:
created() {
this.$watch(
() => this.listMenu[4].value,
function(val, old) {}
)
}
//第二种方法:
computed:{
watchInputData(){ return this.listMenu[4].value }
},
watch:{
watchInputData() {
//这里即可监听到
}
}
- watch监听对象元素
/*普通watch无法监听到对象内部属性变化,只有data中数据改变时才能监听变化。
因此可添加deep属性:深层遍历,会监听对象内所有属性都变化。注意监听数组的变更不需要这么做。*/
watch: {
//第一种监听所有属性的变化,直接监听整个属性,消耗大不建议
obj: {
handler(newValue, oldValue) {
console.log("对象所有属性监听", newValue, oldValue);
},
deep: true
},
//第二种监听对象一个属性的变化
"obj.name": {
immediate: true, //true首次加载执行,默认false
handler(newValue, oldValue) {
console.log("单个属性监听", newValue, oldValue);
}
},
}
同样也可以设置计算属性computed来监听
omputed: {
getName: function() {
return this.obj.name
}
}
watch: {
getName: {
handler: function() {
//监听
},
}
}
修饰符
v-model修饰符
- .lazy
在默认情况下,v-model在每次input事件触发后将输入框的值与数据进行同步。可以使用lazy修饰符,从而转为change事件之后进行同步。
- .number
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符,当输入框失去焦点后将字符串转换成数字。
- .trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:
事件修饰符
- .stop
- .prevent
- .capture
...
- .self
...
- .once
...
- .passive
...
注意:不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。
按键修饰符(@keyup.Enter=“show”||@keyup.13=“show”)
keyCode 的事件用法已经被废弃了并可能不会被最新的浏览器支持。
为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
-
Vue中常用的按键别名
- 回车=>Enter
- 删除=>delete
- 退出=>esc
- 空格=>space
- 上=>up
- 下=>down
- 左=>left
- 右=>right
- tab=>tab(tab键不能用keyup需要用keydown,因为在按下tab的时候输入框失去了焦点,使tab无法触发)
不同的键(系统修饰键,配合keyup使用必须按下修饰键的同时再按下其他键,然后释放其他键,事件才能触发。配合keydown使用直接触发。)
- ctrl=>ctrl
- alt=>alt
- meta=>meta
- shift=>shift
-
在函数中打印e.key,e.keyCode可以得到按键的值
-
.exact 修饰符
.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。
- 鼠标修饰符
- left
- right
- middle
自定义事件
过渡动画
过渡类名
- v-enter
定义进入过渡的开始状态
- v-enter-active
定义进入过渡生效时的状态
- v-enter-to
- v-leave
定义离开过渡的开始状态
- v-leave-active
定义离开过渡生效时的状态
- v-leave-to
混入
混入提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。
但是,如果混入有和原本相同的函数或参数怎么办呢?当发生冲突时,以组件的数据优先。
同名钩子将合并成为一个数组,另外,混入对象的钩子将在组件自身钩子之前调用。
两个对象键名冲突时,取组件对象的键值对。
全局混入
使用全局混入的时候要小心,因为这样会让全局的组件都有混入的数据。
Vue.mixin({
created: function () {
console.log('created');
}
})
自定义指令
Vue中有一些内置的指令,如v-model和v-show,在Vue中一般是不操作DOM的,但是,有的情况仍然需要操作DPM元素进行底层操作,这时候就需要使用自定义指令了。
接下来我们来实现一个进入页面输入框直接获取焦点的事件。
//在全局中注册指令
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
//在局部注册指令
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
看到上面的代码你肯定会想inserted是什么呢,他是钩子函数,看下面的介绍。
钩子函数
- bind
只调用一次,我在想有什么时候是只调用一次指令的呢,就想到了刚才那个进入页面自动获取焦点的指令就可以使用bind钩子,毕竟它只有在进入页面的时候才使用一次。但是,我尝试了一下,结果发现指令没有生效,这是为什么呢?我尝试输出了一下el代码如下:
directives:{
focus:{
bind:function(el){
console.log(el);
}
}
}
结果输出的是input#ipt,然后我又使用延时器延时一秒后再次输出el
directives:{
focus:{
bind:function(el){
setTimeout(()=>{
console.log(el);
},1000)
}
}
}
结果这次输出的是,这说明在真实DOM还没有加到页面上的时候,就已经调用了bind钩子,所以触发不了焦点事件。那既然bind钩子是在DOM还没有渲染到页面上就发生了,那么bind到底有什么用呢?然后我想,那可不可以给它设置样式呢,代码如下:
你好啊
directives:{
color:{
bind(el,binding){
el.style.color = binding.value
}
}
}
但是报错了,说red没有定义,这应该是Vue将red解析成data里面的数据了,把代码改成一下结果就行了。
你好啊
-
inserted
被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)
-
update
-
componentUpdated
指令所在组件的VNode及其子VNode全部更新后调用
-
unbind
只调用一次,指令与元素解绑时调用。这里我又有疑问了,什么时候指令才和元素解绑呢?我在想是不是Vue删除DOM的时候算是解绑呢?哪Vue又在什么时候删除DOM呢?这时候我想到了v-if,v-if为false的时候是不让元素显示,结果就是当DOM被删除的时候unbind钩子会被触发。代码如下。
解绑
钩子函数参数
-
el
指令绑定的元素,可以用来直接操作DOM
-
binding
- name: 指令名,不包含v-前缀
- value: 指令的绑定值,例如:v-color=“‘red’” 中,绑定值为 red。当绑定的值为"1+1"时,返回的值为2。
- oldValue: 指令绑定的前一个值,仅在update和componentUpdated 钩子中可用,无论值是否改变都可用。
- expression: 字符串形式的指令表达式,和value参数相似,只不过它返回的是字符串形式,也就是说"1+1",返回的仍是"1+1"。
- arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
- modifiers: 一个包含修饰符的对象,例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
-
vnode
Vue编译生成的虚拟节点。
-
oldVnode
旧的虚拟节点,仅在update 和 componentUpdated 钩子中可用。
注意:除了el之外,其他参数都是应该只读的,切勿进行修改,如果需要在钩子间共享数据,建议通过元素的dataset来进行。
动态指令参数
v-color:[argument]="value"
函数简写
在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如这样写:
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
对象字面量
我在想如果需要传多个数据,自定义指令应该怎么写呢?这就要用到对象字面量了。
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
这时我又想,如果使用的是对象字面量,那么字面量还是data中的数据吗?我尝试了一下,是可以的,字面量仍然可以联系到data中的数据。但是,我试了试自定义指令中的this应该是指向window的。
插件
插件通常用来为Vue添加全局功能。插件的功能一般为一下几种(没有严格限制)。
- 添加全局的方法或者property,我的理解是给Vue的原型上添加方法。
- 添加全局资源,指令、过滤器、过渡……
- 通过全局混入来添加一些组件选择,这里我
过滤器
Vue允许自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。
{{ message | capitalize }}
过滤器的值是filters
filters:{
cap(value){
if (!value) return ''
value = value.toString()
return value.toUpperCase()
}
},
过滤器也可以全局设置,使用Vue.filter(‘过滤器名称’,function(value){})