VUE基础
冻结属性 Object.freeze(data);
app.key = value;的方式进行响应式修改数据
app.$watch(key, function(old.new))添加数据监听
输入html片段 使用指令v-html
响应式数据 数据驱动模板
v-bind:attr绑定html属性到标签带上,可以实现动态绑定,如果固定的绑定可以直接设置属性
模板解析支持表达式的逻辑运算,三目运算,连字符,数学运算,函数调用等等
方法绑定 v-on:click="function",简写方式@click="function"
样式绑定v-bind:style,简写方式:class :style可以忽略v-bind,控制class是否应用:class="{divClass:false,spanClass:true}",支持数组的写法:class="[divClass, spanClass]"
编译时&运行时
- 完整版:同时包含编译器和运行时的版本。
- 编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。
- 运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。基本上就是除去编译器的其它一切。
如果需要在客户端编译模板,比如传入字符串给template选项,或挂载到一个元素上并以其DOM内部的h作为模板,就需要加编译器,style内联样式绑定,支持对象和数组的方式数组是对象方式的集合,key支持驼峰命名的编写方式,也支持短斜杠的链接方式需添加引号,
// 需要编译器
new Vue({
template: '<div>{{ hi }}</div>'
})
// 不需要编译器
new Vue({
render (h) {
return h('div', this.hi)
}
})
当使用vue-loader或vueify的时候,*.vue文件内部的模板会在构建时预编译成javascript,最终打好的包实际上是不需要编译器的,所以只用运行时版本即可比完整版本小30%,如果非要用完整版本
webpack
module.exports = {
// ...
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' // 用 webpack 1 时需用 'vue/dist/vue.common.js'
}
}
}
Rollup
const alias = require('rollup-plugin-alias')
rollup({
// ...
plugins: [
alias({
'vue': require.resolve('vue/dist/vue.esm.js')
})
]
})
vue对象
所有的vue组件都是vue实例,并且接受相同的选项对象
Vue实例暴露了一些有用的实例property与方法,以前缀¥开头,以便区分用户定义的property
- vm.$data
- vm.$el
- vm.$watch('a',function)
生命周期
生命周期钩子中,this指向调用它的vue实例,
计算属性&监听属性&方法
计算属性,依赖的值进行修改,那么数据会进行修改,如果是其他的值进行修改会从缓存中读取数据
函数的方式绑定计算属性,每次都会计算,非依赖的数据发生变化也会触发修改,方法计算没有缓存,一对多推荐
监听属性,监听data中的值变化,根据key区别,如果需要监听多个值的变化需要分别填写,也是存在缓存,多对一推荐
v-if和v-show
惰性:初始条件为false不会渲染
v-if、v-elseif、v-else,需要连着写才能正常解析,多个标签的显示和隐藏使用<template>标签包裹不支持使用v-show,v-show需要使用dom标签的显示异常
v-for
for in
vue不能将检测到数组下标的更改,通过数组下标进行添加和更高都不能触发
对象的数据更新,如果后添加的一些数据,不能触发响应式
this.$set(this.dataArr, 0 {});修改数组并且触发响应式的方法
变异方法push、pop、shift、unshift方法也都会触发响应式
object.assign可以添加多个属性到响应式
v-for的优先级高于v-if,不建议在v-for中使用v-if,如果同时访问一个数据就存在优先级问题
==使用计算属性对数据进行过滤,源头进行修改数据,防止v-for和v-if同时使用==
事件处理
v-on:eventKey
:eventKey
.stop .self .once .prevent
@click默认添加了阻止默认操作
input回车提交 v-on:keyup.enter v-on:keyup.tab v-on:keyup.esc v-on:keyup.up 添加事件监听
自定义键盘码 Vue.config.keyCode.xxx = 87; v-on:keyup.xxx
表单绑定
input
textarea
select
radio
checkbox
v-model指令,创建双向数据绑定
自身标签的value属性设置后不起作用
checkbox可以绑定为数组中的值,自动识别添加到数组中
checkbox和radio需要设置value值
select第一个值一般用于给用户设置提示“请选择”,设置为disable属性,多选multiple属性,v-model值绑定为数组
修饰符
v-model.lazy=""
- .lazy,失去焦点的时候触发
- .number用户输入自动转换为数字类型
- .trim
组件基础
创建全局
可服用vue实例
Vue.comonent("name", {
data:function(){
return {
}
},
template: '',
methods:{
},
watch{
},
computed:{
},
beforeCreated(){
},
created(){
},
destroyed(){
}
})
html中大小写不明感,所以使用小写加短横线的方式命名
注册组件的时候可以使用驼峰命名或者端横岗链接的方式,使用的时候只能使用短横杠链接的方式
数据传递,单向数据流 props:[]
父级v-bind:xxx-xxx="",子组件可以使用驼峰命名法进行获取
局部组件
const inputItem = {
data:function(){
return {
}
},
template:''
}
在vue的components属性中引入
全局组件就算不使用也会打入包中
组件通讯
父传子
v-bind属性绑定,子组件props:[]获取 this.$parent获取到父级的实例,可以调用父级的属性和方法
子传父
#emit事件监听传值,父组件中v-on:监听的事件 $child
兄弟组件
bus中央事件总线,非空的vue实例作为中央事件,结合实例方法$on $emit
Vue.property.$bus = new Vue();
//子组件发送
this.$bus.$emit('sendMsg', this.message);
//兄弟节点接受
this.$bus.$on('sendMsg', data => {
});
注册的$bus要及时销毁
import Vue from 'vue';
const Bus = new Vue();
data:{
Bus
}
将bus挂载到Vue根对象上
推荐使用
import Vue from 'vue';
const Bus = new Vue();
export default Bus;
那个页面需要使用就引入
vuex
管理所有组建的状态,状态管理模块
深层次嵌套
依赖注入的方式,不推荐直接用于应用程序代码中,建议在库和高阶组件中使用
父组件provied 子组件中通过inject获取
$attr/inheriAttrs,父组件通过属性传递,子组件通过$attr获取,需要逐层传递,根节点设置inheriAttrs为fasle 属性值就不会显示在dom节点上
组件深入
插槽
普通插槽
slot 占位符的作用
父组件给子组件传递组件后者dom节点
<slot>默认值!</slot>
具名插槽
v-slot指令配合name属性使用
想要按照自定义的位置显示父级传递过来的dom或者组件
<child>
<template v-slot:header><p></p></template>
</child>
<div>
<slot name="header"></slot>
</div>
具名插槽会放置到固定的位置,不具名的插槽默认插入数据
可以自定义默认插槽
<temolate v-slot:default></template>
作用域插槽
让插槽内容可以访问到子组件中才有的数据
子组件中定义的数据,父组件中使用插槽,在插槽中使用子组件定义的数据
<child>
<template v-slot:header="slotProps"><p>{{slotProps.lastName}}</p></template>
</child>
<div>
<slot name="header">{{'默认值'}}</slot>
</div>
注意:
- 默认插槽如果需要拿数据,在组件的属性上填写v-slot="",如果存在具名插槽,默认的插槽就不能略写
动态切换组件
<component v-bind:is="component-name"></component>
动态组件状态缓存,keep-alive
使用keep-alive包过就可以实现组件状态缓存-实际缓存的是虚拟dom
过度动画
transtion标签
<transition name="">
<p v-show="isShow"></p>
</transition>
name-enter-active,name-leave-to{}
进入状态
.xx-enter{
}
.xx-enter-to{
}
离开状态
.xx-leave{
}
.xx-leave-to{
}
//如上写法繁琐,可以简写
name-enter-active,name-leave-to{}
.xx-enter,.xx-leave-to{
}
name会自动添加两个类name-enter-active name-leave-to
p元素显示或隐藏以后会移除对应的两个class
这来跟类可以自己定义类里面的效果内容
设置CSS动画
推荐的方式
@keyframes bounce-in{
0%{
transform:scale(0)
}
50%{
transform:scale(1.5)
}
100%{
transform:scale(1)
}
}
@keyframes bounce-out{
0%{
transform:scale(1)
}
50%{
transform:scale(1.5)
}
100%{
transform:scale(0)
}
}
.xxx-entry-active{
animation: bounce-in 2s linear
}
.xxx-entry-leave{
animation: bounce-out 2s linear
}
可以自定义过度类名,配合第三方库使用
<transition enter-active-class="animaited tade" leave-active-class="animaited tade">
<p v-show="isShow"></p>
</transition>
通过属性设置
多个元素过度:渲染后内部职能有一个子元素
当有相同的元素名进行切换,需要设置key属性进行唯一标记
过度模式:默认是元素进入离开同时发生,设置mode属性in-out新元素先进行过度完成之后当前元素过度离开,out-in当前元素先过度完成之后新元素过度进入
js动画库
钩子函数
<template
@before-enter=""
@enter="";
@after-enter="";
@before-leave="";
@leave="";
@after-leave="";>
</template>
Velocity
必须声明done钩子回调,否则过度会立即完成
appear也可以添加calss
appear-active-class
对列表进行过度
transition-group以一个真实元素进行渲染
<transition-group
name="bounce"
tag="div"
>
</transition-group>
vue会对元素进行复用,所以需要给列表添加key
指令
- v-text更新文本
- v-html
- v-if v-else v-else-if
- v-show
- v-for
- v-model
- v-on
- v-bind
自定义指令
//输入框页面加载获取焦点
Vue.directive("focus", {
inserted:function(){
//被插入父节点就会触发此钩子
el.focus();
}
})
//使用
v-focus
自定义指令钩子函数
- bind 只会调用一次,当指令第一次绑定到元素的时候触发
- inserted绑定元素插入父节点的时候调用
- update节点更新时触发钩子
- componentUpdate组件节点进行更新时候触发
- unbind解绑,也只调用一次
function(el,binding,vnode,oldnode)参数
- el指令绑定的元素
- binding对象,name指令名称、value指令绑定名称、oldValue上一值,arg指令穿的参数v-focus:xx=""这里的xxx,modifiers v-focus.foo这里的foo,vnode虚拟节点,oldNode update和componentUpdate中才有
vue3变化
速度更快
体积更小
更易于维护
更面向原生开发
更易于开发使用
虚拟DOM重写
优化插槽生成
静态树提升
静态属性提升
基于Proxy的观察者机制
从flow转向type
解耦,使内容更加模块化
编译器重写
运行时与平台无关
Vue cli创建项目
node_module->@vue->cli-service->webpack.config.js
可以在根目录下新增vue.config.js会自动进行合并,文件下的configureWebpack对象下配置
需要注意:输出路径等
查看配置:npx vue-cli-service inspect --mode peoduction
npx vue-cli-service inspect --mode peoduction >> xxx输出到文件中进行查看
vue-router
route
routes
router
onhashchange hash模式
history pushState replaceState
兜底路由全匹配,放到路由集合的最下面,设置redirect重定向到起码路由
$router.params.name获取路由参数
vue如果只是修改小部分,路由被重新触发可能不会引起页面生命周期重新触发
页面中添加路由变化
watch:{
$route(from,to){
}
}
路由嵌套
children属性设置
编程式导航
标签导航
路由导航this.$router.push()/replace(); this.$router.go()
命名路由,可以通过名称进行访问
push可以接受对相爱你给参数设置name属性也可以实现同样会的效果
路由传参{name:'',query:{}},使用params传值就使用params获取,使用query传值就使用query取值
传参有区别,一个会显示在地址栏一个不会显示在地址栏,不显示在地址栏进行刷新就会获取不到值
params类型传值,不建议使用path建议使用name进行路由配置
路由守卫
进入路由之前进行拦截检查
全局钩子函数
//首页new的router对象 router.boforeEach(to,form,next);
放行next()
阻止next(false);
重定向next('/login');
next(error) ->监听router.onError()
适合配置权限使用,权限控制
可以通过全局钩子每次跳转后都将滚动条滚动到起始window.scrollTo(0,0);
也可以打印log信息
组件内钩子函数
beforRouteEnter(to,from,next)//不能使用this,组件还没创建 beforRouteUpdate(to,from,next) beforRouteLeave(to,from,next)
可以在导航完成之前获取数据 执行next进入路由,缺点是用户会停留在前一个页面
导航完成之后获取路由就可以使用组件的生命周期实现
Vuex
状态管理模式
通过规则进行获取和修改数据,达到数据状态可追踪,可预测
import Vue form 'vue';
imnpoet Vuex from 'vuex';
//注册
Vue.use(Vuex);
const moduleA = {
state:{},
motations:{},
actions:{},
...
}
const moduleB = {
state:{},
motations:{},
actions:{},
...
}
export default new Vuex.Store({
//添加属性后所有的action motations等变成了局部 dispatch触发的时候就需要使用传值路径为m2/modifyName
namespace:true,
state:{
//状态数据
list:[1,2,3,4,5,6,7,8,9,10]
},
motations:{
//唯一改变state的方式
add(state){
return state.count++;
},
reduce(state){
return state.count--;
},
//支持设置未存在的值,加入响应式
addNewState(state){
//方式一
Vue.set(state, 'newState', '我是新添加的值');
//方式二
this.replaceState({...state,newState:'新添加的值'});
},
changeCount(state, newState){
Vue.set(state, 'newState', '新值');
}
},
actions:{
//异步操作
modifyCount(context, newValue){
setTimeout(() => {
context.commit('changeCount',{count:200});
});
}
},
modules:{
//模块化操作
//所有的数据都放在一个state中,随着项目体量增大,会造成代码可读性下降,所以需要模块化的管理
m1:moduleA,
m2:moduleB
},
getter:{
//compute计算属性,可以先对数据进行计算,主要是对状态处理
filterList(state){
return state.list.filter(n => n%2 === 0);
}
}
});
//根实例进行注册
new Vue({
router,
store,
render:h=>h(App)
}).$mount('#app');
//组件中使用
//在计算属性中使用可以实时监听到数据的变化
import {mapState, mapGetters,mapMutations,mapActions} from 'vuex';
compute:{
//使用辅助函数
...mapState(['count']);//推荐书写
//可以使用别名
//...mapState({c:'count', newValue:state=>state.newValue ? state.newValue : '我是默认值'});//推荐书写
//count(){
// this.$store.state.count
//}
...mapActions({handleAction:'modifyCount'}),
...mapGetters(['filterList'])
//可以定义别名
//...mapGetters({arr:'filterList'})
//getArr(){
// this.$store.filters.filterList
// }
//获取模块中的数据
moduleName(){
return this.$store.state.m1.name;
}
}
methods:{
add(){
//触发修改,可以传多个值
this.$store.commit('add',{});
},
handleChange(){
this.$store.dispatch('modifyCount');
}
}
模块可以进行嵌套 访问可以通过路径查询m1/m2/xxx
在模块化的基础上,设置了命名空间,如果想要访问全局的一些 action和mutations
//actions
dispatch('modifyCount', null, {root:true});
//mutations
commit('changeCount', null, {root:true});
//getter
get(state,getter,rootState,rootGetters){};