Vue的特点?
1、vue采用组件化模式,提高代码的复用率,维护性更好
2、声明式编码,无需直接操作dom,提高开发效率
3、使用虚拟DOM+diff算法,尽量复用dom节点。
Vue中的两种数据绑定的方式
1、单向数据绑定(v-bind):数据只能从data流向页面
2、双向数据绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
注意:
(1):双向绑定一般应用在表单类元素上(input、select)
(2):v-model:value="" 可以简写成 v-model="",v-model默认收集的就是value属性的值
(3):v-model不能绑定props传过来的值,props传过来的值不能修改
3、v-model收集表单数据
若:<input type="text"> v-model收集的是value值,输入的就是value值
若:<input type="radio"> v-model收集的是value值,需要给标签设置value值
若:<input type="checkbox">
(1):没有配置value属性,那么收集的就是checked的值
(2):有配置value属性
1、v-model的初始值不为数组,收集的就是checked的值
2、v-model的初始值为数组,收集的就是value的值组成的数组
v-model的三个修饰符
v-model.lazy : 失去焦点后在收集数据
v-model.number: 收集的数据转换为数字
v-model.trim : 删除首位的空客
怎样理解Vue中的MVVM模型?
MVVM模型分为三层部分:
1、M: 数据层(可能是我们自己写的固定数据,也可能是来自服务器的数据)
2、V: 视图层(DOM层,给用户展示数据)
3、VM:视图模型层:视图层和数据层沟通的桥梁,一方面实现了数据绑定,实时的将数据层中数据改变反应到视图层,
另一方面是实现了DOM监听,DOM发生了一系列的事件是,在一定的情况下对数据层中的数据进行对应的改变
Vue中事件修饰符
1、prevent :阻止默认事件
2、stop: 阻止事件冒泡
3、once:只触发一次事件
4、capture: 使用事件的捕获模式
5、self: 只有event.target是当前操纵的元素时才触发事件
6、passive:事件的默认行为立即执行,无需等待事件回调执行完毕
计算属性
1、定义:要用的属性不存在,要通过已有的属性计算得来
2、原理:底层借助了Object.defineproperty方法提供的getter和setter
3、get函数的执行时机?
(1)、初次读取时会被执行一次
(2)、当依赖的数据发生改变时会再次调用
4、优点:与mmethods相比,内部有缓存机制,可复用,效率更高。
5、计算属性要被修改,必须写set函数去响应修改。计算属性会出现在vue的实例上,直接使用即可
深度监视
(1)、Vue中的watch默认不监测属性为对象时对象内部值的改变
(2)、配置deep:true可以监测属性为对象时对象内部值的改变(多层)
计算属性和监视属性的区别?
1、计算属性能完成的功能,监视属性也可以
2、监视属性能完成的功能,计算属性不可以(监视属性可以进行异步操作,计算属性不能)
React/Vue中的key有什么作用?(key的原理是什么?或为什么遍历列表时,key最好不要用index)
1、key的作用
当状态中的数据发生改变时,react会根据新数据生成新的虚拟DOM,随后react进行新虚拟DOM于旧虚拟DOM比较,
比较规则:1、旧虚拟DOM找到了与新虚拟DOM相同的key
(1)、若虚拟DOM中的内容没变,直接用之前的真实的DOM。
(2)、若虚拟DOM的内容变了,则生成新的真实DOM,最后替换页面中之前的真实DOM
2、旧虚拟DOM中未找到与新虚拟DOM相同的key
(1)、根据数据创建的新的真实DOM,随后渲染到页面
2、用index做key时可能会引发的问题
(1)、若对数据进行:逆序添加、逆序删除、等破环顺序的操作 会产生没必要的真实DOM的更新 效率较低
(2)、如果结构中还包含输入类的DOM: 会产生错误的DOM更新
(3)、如果不存在逆序对数据的操作,用index做key是没问题的
3、开发中如何选择key
(1)、最好使用每条数据的唯一标识作为key
Vue中监测数据的原理
1、vue会检测data中所有层次的数据
2、对象数据的检测
(1)、通过setter实现监测、要在创建vue的实例对象时要传入数据
(2)、后续添加的属性,Vue默认不做响应式处理
(3)、如需给后续添加的属性做响应式处理
(1)、Vue.set(target,属性名,属性值)
(2)、vm.$set(target,属性名,属性值)
3、数组数据的监测
1、通过包装数组更新元素的方法实现监测
(1)、调用原生数组的方法对数组进行更新
(2)、重新解析模板,进而更新页面
2、Vue中用以下方法对数组进行操作会做响应式的处理
(1)、push(),pop(),shift(),unshift(),splice(),sort(),reverse()
(2)、Vue.set(target,index,value)或vm.$set(target,index,value)
4、切记:Vue.set()和vm.$set(),不能给vm或vm的根数据对象(data),添加属性
v-xxx其他指令的作用
1、v-once指令(没有值):
(1)、v-once所在的节点在初次动态渲染后,就视为静态内容了
(2)、以后数据的改变不会引起v-once所在的节点更新,可以用于优化性能
2、v-cloak指令(没有值):
(1)、本质是一个特殊的属性,Vue实例创建完毕并接管DOM容器后会删除v-cloak属性
(2)、与css配合可以解决因网速过慢而将未渲染好模板渲染到页面上
3、v-text指令:
(1)、作用:向其所在的节点渲染文本内容(v-text的属性值)
(2)、v-text会替换掉节点中的内容
4、v-html指令:
(1)、作用:向其所在的节点渲染包含html结构的内容,识别html结构
(2)、v-html会替换掉节点中的内容
(3)、具有安全性问题
1、在网站上动态渲染Html非常危险,容易导致xss攻击
2、要在可信的内容上用v-html,永不要用在用户提交的内容上
5、v-pre指令(没有值):
(1)、跳过其所在的节点的编译过程
(2)、可以用他跳过,没有使用指令语法,插值语法的节点,加快编译
自定义指令
1、定义语法
(1)、局部指令:
new Vue({
directives: {
指令名:{配置对象}
}
})
或
new Vue({
directives: {
指令名:回调函数
}
})
(2)、全局指令:
Vue.directive(指令名:{配置对象}) 或 Vue.directive(指令名,回调函数)
2、配置对象中常用的三个回调 this指向window
(1)、bind(): 指令与元素绑定成功时调用
(2)、inserted():指令所在的元素插入页面时调用
(3)、update(): 指令所在的模板被重新解析时调用
3、例子:
new Vue({
directives: {
fbind: {
bind(element,binding) {
element.value = binding.value * 10
},
inserted(element,binding) {
element.focus()
},
update(element,binding) {
element.value = binding.value * 10
}
}
}
})
new Vue({
directives: {
big(element,binding){
element.innerHTML = binding.value * 10
}
}
})
Vue.directive('big',function(element,binding) {
element.innerHTML = binding.value * 10
})
4、指令名不要用驼峰命名法,要用word-word的方法
生命周期
webStorage(浏览器存储)
1、存储内容一般为5MB左右,不同的浏览器不同
2、浏览器通过window.localStorage和window.sessionStorage的属性来实现本地存储
3、API:
(1): window.local(session)Storage.setItem('key','value') //接受一对键和值进行存储,
key和value都为字符串
(2): window.local(session)Storage.getItem('key') //返回键名对应的值,不存在返回null
(3): window.local(session)Storage.removeItem('key') //删除该键值对
(4): window.local(session)Storage.clear()//清空
4、
(1)、sessionStorage存储的内容会随着浏览器的关闭而清空
(2)、localStorage存储的内容,只有手动清除
(3)、JSON.parse(null)的结果仍是null
消息的订阅与发布
1、一种组件间的通信方式
2、使用步骤
(1):安装pubsub-js库 (npm install pubsub-js)
(2):引入 import pubsun from 'pubsub-js'
(3):接受数据,在接受消息的组件订阅消息
mounted() {
this.pubsubId = pubsub.subscribe('消息名',(msgName,data) => {
//回调函数有两个参数,第二参数即为发送的数据
//data即为发送过来的数据
})
}
(4):发送数据
pubsub.publish('消息名',data)
3、最好在beforeDestory的周期函数中,用pubsub.unsubscribe(this.pubsubId)去取消订阅
$nextTick(回调函数)
作用:在下一次DOM更新结束执行其指定的回调
用的时机:当改变数据后,要基于更新后的DOM进行某些操作,要在$nextTick所指定的回调函数中执行
Vuex
1、环境搭建
安装vuex(npm i vuex)
在src文件夹下创建Store文件夹,并在其中创建一个index.js
index.js的配置代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const actions = {}
const mutations = {}
const state = {}
export default new Vuex.Store({
actions,
mutations ,
state
})
在main.js文件夹其中的配置
import store from './src/Store/index.js'
new Vue({
render: h => h(App),
store
}).$mount('#app')
2、mapSate方法从state中读取数据
假如state中的数据如下:
const state = {
sum:0,
school: '某某某大学',
student: '某某某'
}
//mapState
computed: {
...mapState({sum:'sum',school:'school',student:'student'})
或
...mapState(['sum','school','student'])
}
3、mapGetters方法从getters中读取数据
假如getters中的数据如下:
const getters = {
bigSum(state) {
return state.sum * 10
}
}
//mapGetters
computed:{
..mapState({bigSum:'bigSum'})
或
...mapState(['bigSum'])
}
4、mapMutations 会帮助我们与mutations对话
const mutations = {
increment(state,value) {
state.sum += value
},
decrement(state,value) {
state.sum -= value
}
}
//mapMutations
methods:{
...mapMutations({increment:'increment',decrement:'decrement'}),
或
...mapMutations(['increment','decrement']),
}
5、mapActions 会帮助我们与actions对话
const actions = {
incrementOdd(context, value) {
if (context.state.sum % 2 ) {
context.commit('increment',value)
}
},
delayIncrement(context,value) {
setTimeout(() => {
context.commit('increment',value)
},1000)
}
}
//mapActions
methods: {
...mapActions({incrementOdd:'incrementOdd',delayIncrement:'delayIncrement'}),
或
...mapActions(['incrementOdd','delayIncrement']),
}
备注:mapActions与mapMutations使用参数时,若需要传递参数,在模板绑定事件时要传递好参数,否则传递的参数是事件对象
创建路由器并配置路由
1、npm i vue-router
2、在src文件夹下创建router文件,并在该文件内创建index.js
3、src/router/index.js的内容代码如下:
import Vue from 'vue
import VueRouter from 'vue-router'
Vue.use(VueRouter)
export default new VueRouter({
routes: [
{配置路径和对应的路由组件},
{配置路径和对应的路由组件},
{配置路径和对应的路由组件},
]
})
4、main.js代码如下:
import router from './router/index'
new Vue({
render: h => h(App),
router
}).$mount('#app')
5、基本使用:
<router-link to="path(路径)"></router-link>//跳转组件
<router-view></router-view> //组件显示的位置
6、路由传参:
query参数:
(1):<router-link :to="`path(路径)?id=${参数}&name=${参数}`"></router-link>
(2):<router-link :to="{
path:'path(路径)',
query: {
id:'id',
name: 'name'
}
}"></router-link>
params参数:
(1):在配置路由时要使用占位符声明接受params参数
{
path:'/home/:id/:title'
component: Home
}
(2):<router-link :to="`path(路径)/${id}/${title}`"></router-link>
(3):<router-link :to="{
name:'路由的别名', //必须这样写
params: {
id:'id',
name: 'name'
}
}"></router-link>
7、获取参数
{{$route.query(params).id}}
{{$route.query(params).name}}
8、路由的props配置:
{
path: 'detail',
component: Detail,
// props: {a:1,b:100}
// props:true //值为true把该路由收到的所有参数以props的形式传递给Detail组件
props(route) { //该函数返回的对象以props形式传递给Detai组件
return {
id: route.query.id,
title: route.query.title
}
}
}
9、router-link标签的replace属性
(1)作用:控制路由跳转时操作浏览器记录的模式
(2)浏览器历史记录有两种写入方式:分别为push和replace,push是追加历史记录,replace是替换当前记录,默认为push
(3) 开启replace模式 <router-link replace></router-link>
10、编程式路由导航
(1):不借助<route-link>实现跳转
(2):
this.$router.push({
name: '路由的名字',
params: {
id: 'id',
title: 'title'
}
})
his.$router.replace({
name: '路由的名字',
params: {
id: 'id',
title: 'title'
}
})
(3):this.$router.back() //后退
(4):this.$router.forward()//前进
(2):this.$router.go(number) //number为正前进,number为父后退。
11、缓存路由组件
作用:让不展示的路由组件保持挂载,不被销毁
//包括在includes属性里的组件才会缓存,不写该属性,默认所有在下方展示的组件都会缓存。
<keep-alive include="组件名"> //缓存一个
<router-view></router-view>
</keep-alive>
<keep-alive :include="['组件名','组件名']"> //缓存多个
<router-view></router-view>
</keep-alive>
12、路由组件所独有的生命周期函数
1、activated 路由组件激活时触发
2、deactivated 路由组件失活时触发
13、路由守卫
作用:对路由的权限进行控制
1、全局守卫
(1):全局前置守卫
初始化时调用、切换之前调用
//对路由的权限进行判断
//成功进行跳转 否者不跳转
router.beforeEach((to,from,next) => {
if (to.meta.isAuth) {
if (localStorage.getItem('school') === 'atguigu') {
next()
} else {
alert('暂无权限查看')
}
} else {
next()
}
})
(2):全局后置守卫
//初始化时调用、切换之后调用
router.afterEach((to,from) => {
//一般用的较少,但会用于路由跳转之后改变网页的title
if (to.meta.title) {
document.title = to.meta.title
} else {
document.title = 项目名
}
})
2、独享路由守卫(只有前置)在某个路由内部进行配置
beforeEnter((to,from,next) => {
if (to.meta.isAuth) {
if (localStorage.getItem('school') === 'atguigu') {
next()
} else {
alert('暂无权限查看')
}
} else {
next()
}
})
3、组件内路由守卫(在组件中进行配置)
//通过路由规则进入该组件时,被调用
beforeRouteEnter((to,from,next) => {
if (to.meta.isAuth) {
if (localStorage.getItem('school') === 'atguigu') {
next()
} else {
alert('暂无权限查看')
}
} else {
next()
}
})
//通过路由规则离开该组件时,被调用
beforeRouteLeave((to,from,leave) => {
next()
})
ElementUI按需引入样式的配置和使用的步骤
1、安装(npm i element-ui)
2、babel.config.js文件中的配置
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
["@babel/preset-env", { "modules": false }]
],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
3、main.js文件代码
import {Button,Row,DatePicker} from 'element-ui' //引入所要用到的样式
Vue.component(Button.name,Button)
Vue.component(Row.name,Row)
Vue.component(DatePicker.name,DatePicker)