Vue基础介绍
Vue
简介
Vue是一套用于构建用户界面的渐进式框架
优点
- 学习成本低、轻量级的框架、渐进式框架
- 双向数据绑定、组件化开发
- 单页面路由、虚拟dom
- 数据和结构的分离、运行速度快、插件化
缺点
- 不支持IE8以下
- 生态系统可能没有Angular和React那么丰富
- 单页面应用,不利于seo优化
- 初次加载时耗时多
常用指令
指令 | 说明 | 示例 |
---|---|---|
v-if | 控制元素渲染,值为true重新加载dom, v-else-if和v-else同理 | <div v-if="true">渲染元素</div> |
v-show | 控制元素显示,值为false相当于css的display:none | <div v-show="false">隐藏元素</div> |
v-text | 元素的InnerText属性,用于填充文本 | <div v-text="显示的文本"></div> |
v-html | 元素的innerHTML属性,用于填充文本或富文本 | <div v-html="html"></div> , html 在data中声明 |
v-model | 双向绑定,视图层修改值时会同步改变数据层的值 | <input v-model="value" /> , value 在data中声明 |
v-bind | 给元素的属性赋值, v-bind:属性名="常量/变量名" ,简写形式:属性名="变量名" |
<img v-bind:src="imgUrl"/> 或 <img :src="imgUrl"/> |
v-on | 自定义事件, v-on:事件名="表达式/函数名" ,简写形式@事件名="表达式" |
<div v-on:click="clickEvent"></div> 或 <div @click="clickEvent"></div> |
计算属性和侦听器
计算属性
计算属性是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变时它们才会重新求值。
1 | <div id="app"> |
1 | var vm = new Vue({ |
侦听器
当需要在数据变化时执行异步或开销较大的操作时,使用侦听器是最有用的
1 | var vm = new Vue({ |
修饰符
事件修饰符
1 | <!-- 阻止单击事件继续传播 等同于event.stopPropagation() --> |
其他
1 | <!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` --> |
生命周期
基本生命周期 | 说明 |
---|---|
beforeCreate | 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。 |
created | 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el property 目前尚不可用。 |
beforeMount | 在挂载开始之前被调用:相关的 render 函数首次被调用。 |
mounted | 实例被挂载后调用。 |
beforeUpdate | 数据更新时调用。 |
updated | 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。 |
beforeDestroy | 实例销毁之前调用。在这一步,实例仍然完全可用。 |
destroyed | 实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。 |
不常用生命周期 | 说明 |
---|---|
activated | 被 keep-alive 缓存的组件激活时调用。 |
deactivated | 被 keep-alive 缓存的组件停用时调用。 |
errorCaptured | 当捕获一个来自子孙组件的错误时被调用。 |
组件传值
父组件
1 | <template> |
子组件
1 | <template> |
兄弟传值
1 | // main.js |
第一个子组件
1 | <template> |
第二个子组件
1 | <template> |
Vuex
1 | import Vue from 'vue' |
挂载
1 | // main.js |
使用
- state
1
2
3
4
5
6<template>
<div id='app'>
<!-- 组件中使用 -->
name: {{ $store.state.name }}
</div>
</template>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48import {mapState, mapMutations, mapActions, mapGetters} from 'vuex'
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
computed: {
// ...mapGetters({
// // 把 `this.getData` 映射为 `this.$store.getters.fullInfo`
// getData: 'fullInfo'
// }),
...mapGetters([
'fullInfo',
]),
getData(){
return this.$store.getters.fullInfo
}
},
methods:{
// ...mapMutations({
// editName: 'edit' // 将 `this.editName()` 映射为 `this.$store.commit('edit')`
// }),
// ...mapActions({
// asyncEditName: 'asyncEdit', // 将 `this.asyncEditName()` 映射为 `this.$store.dispatch('asyncEdit')`
// }),
...mapMutations([
'edit' // 将 `this.edit()` 映射为 `this.$store.commit('edit')`
]),
...mapActions([
'asyncEdit' // 将 `this.asyncEdit()` 映射为 `this.$store.dispatch('asyncEdit')`
]),
getName() {
console.log(this.$store.state.name);
},
getGetterName() {
console.log(this.$store.getters.fullInfo);
},
editName() {
this.$store.commit('edit', 'rose');
// this.$store.commit('edit', {age:15,name: 'rose'});
},
asyncEditName() {
this.$store.dispatch('asyncEdit', {age:15})
}
}
}
路由
1 | <!-- 使用 router-link 组件来导航. --> |
1 | // 1. 定义 (路由) 组件。 |
动态路由
1 | const User = { |
嵌套路由
1 | const User = { |
路由API
编程式导航
router.push(location, onComplete?, onAbort?)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// router.push 等同于 <router-link>
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
// 如果提供了 path,params 会被忽略 , 你需要提供路由的 name 或手写完整的带有参数的 path
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123router.replace(location, onComplete?, onAbort?)
跟router.push
很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。router.go(n)
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。1
2
3
4
5
6
7
8
9
10
11
12// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
导航守卫
1 | const router = new VueRouter({ ... }) |
组件内的守卫
1 | beforeRouteUpdate (to, from, next) { |
常见bug
打包后白屏
1
Refused to apply style from 'http://127.0.0.1:5500/public/assets/css/app.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
1
2
3
4// vue.config.js中添加
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? './' : './'
}子组件改变父组件的数据,父组件元素绑定的值不更新
- 使用
$forceupdate()
- 使用
$emit('update:value',newValue)
- 在父组件methods中改变,子组件触发父组件中的方法
- 使用
v-for绑定的数据更新,视图不更新
原因:由于 JavaScript 的限制, Vue 不能检测以下变动的数组:
当你利用索引直接设置一个项时,例如: vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如: vm.items.length = newLength
解决办法:
1
2
3Vue.setVue.set(example1.items, indexOfItem, newValue)
或 example1.items.splice(indexOfItem, 1, newValue)
example1.items.splice(newLength)使用了前两种方法依旧不更新视图
包裹一层标签,并使用v-if
或v-show
操作
修改data数据后视图层没有同步更新
使用
1
2
3this.$nextTick(()=>{
this.username = 'jack'
})
如果有任何建议或者补充,欢迎在下方评论区留言!
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 哈哈哈哈密瓜 の 博客!
评论
TwikooWaline