一、基础
一、 理解mvvm
1.m 是vue实例中的data,自定义的数据或后端返回的数组不是后端mvc里的model概念不同。
2.vm 是vue的实例 m和v之间的调度者 是mvvm的核心思想
3.v是 html 要渲染的。
二、 常用指令
1.v-cloak 解决{{}}插值闪烁问题
2.v-text 会先执行 覆盖 元素中原本的内容 但是插值表达式只会覆盖自己的占位符,默认不会闪烁
3.v-html 渲染 html标签 覆盖元素中原有元素内容
4.v-bind: 简写为: 用来绑定数据 可以写合法的js表达式
5.v-on: 简写为 @ 用来点击事件
6.v-if:DOM渲染与不渲染,不能和v-for一起使用
7.v-for:循环渲染DOM,循环时要加v-key唯一标识,循环时不能和v-if一起使用,可以用computed计算属性再循环
8.v-model:双向数据绑定,一般用于表单
9.v-show:DOM隐藏与显示,和v-if区别在于v-show是利用css控制,实际上DOM已经渲染了,而v-if是渲染与不渲染。如果DOM频繁切换可以用v-show,反之用v-if。
三、常用事件修饰符
1.stop 阻止冒泡 :外层和里层都有方法 点击里层会产生冒泡,也会触发外层的事件。顺序 从里到外产生事件
2.prevent 阻止浏览器默认行为 :a标签有浏览器默认行为。
3.capture 捕获事件 :点击里层先触发外层再触发里层 顺序从外到里产生事件
4.self 只触发自己本身的事件 不会产生冒泡和捕获事件 类似于阻止冒泡 但只针对自己那一层 最外层还是会被最里层冒泡冒到 stop 是阻止所有层次
5.once 事件只执行一次
四、数据的绑定
1.v-bind: 数据的单向绑定
2.v-modle :数据的双向绑定 这个只能用于表单元素中
tips: 表单元素 radio text address email select checkbox textarea
五、class 绑定
1.数组带对象
<div :class="[classA,classB,{'classC':flag}]" >
data(){
return{
flag:true
}
}
tips:可以在类中的数组中写三元表达式,但推荐使用对象来代替它控制是否渲染
2.单纯的对象
<div :class="{classA:falg1,classB:flag2}" />
data(){
return{
falg1:true,
falg2:true
}
}
3.数组带三元
<div :class="['ac','bd',falg?'active','']" / >
data(){
return{
falg:true,
}
}
4.对象升级
<div :class="classObj" />
data(){
return{
classObj:{classA:falg1,classB:flag2}
}
}
tips:直接使用一个对象数组来控制样式
5.使用style 的对象来实现样式的修改
<div :style="styleObj" />
data(){
return{
styleObj:{color:red}
}
}
6.使用style 的数组带对象来实现样式的修改
<div :style="[styleObj1,styleObj2]" />
data(){
return{
styleObj1:{color:red},
styleObj2:{color:red}
}
}
六、v-for的使用
1. 可以遍历: 普通数组,对象数组,对象,还可以是数字
<div v-for='(item,key,index) in object' :key='index'>
{{item}}--{{key}}--{{index}}
</div>
<div v-for='(count in 10)'> </div>
tips:在遍历对象的时候有多个index索引,遍历数字时是从1开始的。绑定key时属性值必须是number或者string
七、v-if、v-show
1.v-if 有较高的切换性能 , 适合元素可能永远不会被用户看到。
2.v-show 有较高的初始渲染消耗,适合元素频繁切换。
八、 调试插件
1.在谷歌商店找vue-devtools插件,使用这个插件,并设置插件,允许访问文件网址。 会在调试中出现vue相关的东西
2.debugger 直接写可以调试
九、 过滤器
全局和私有过滤器
<div v-for='(item,key) in object' :key='index'>
{{item | dateFormat}}
</div>
<div v-for='(count in 10)'> </div>
全局
vue.filter('过滤器名称',function(value){
return value.replace(/dome/g,'god')
})
私有(局部)
filters:{
dateFormat:function(data,param){
do some
}
}
tips:
data 就是 | 第一个参数已经被定死了,永远是, 管道左边要被转换的数据,param 是过滤方法传进来的其他参数,过滤器采用就近优先原则,如果私有和全局的名称一样就优先采用私有的。
padstart 和 padend es6 的补0方法
第二个参数是字符串,第三个参数是表达式,如果自己定义参数值是动态的会报错,还未找到原因,后期会找时间再看看,目前就是简单的过滤用过滤器,复杂点用方法,能用计算属性用计算属性,有缓存,能提高性能
十、 生命周期
1.beforeCreate():这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它…
2.created(): 这是遇到的第二个生命周期函数…
3.beforeMount():这是遇到的第3个生命周期函数,表示 模板已经在内存中编辑完成,但是尚未把模板渲染(挂载)到页面中。在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串。就像{{text}}这样
4.mounted():这是遇到的第四个生命周期函数,表示内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了。只要执行完这个生命周期,就表示整个vue实例已经初始化完毕了,此时,组件已经脱离了创建阶段,进入到了运行阶段。
5.beforeUpdate():这时候表示,我们的界面还没有被更新[但数据已经被更新了页面中显示的数据,还是旧的,此时data数据是最新的。页面尚未和最新的数据保持同步
6.update() : 这一步执行的是 先根据data中最新的数据,在内存中重新渲染出一份最新的内存dom树,当最新的内存dom树被更新后,会把最新的内存DOM树重新渲染到真实的页面中去,这时候,就完成了数据data(model层)->view(视图层)的更新,
页面和data数据已经保持同步了,都是最新的。
7.beforeDestory :当执行 beforeDestory 钩子函数的时候,Vue实例就已经从运行阶段,进入到销毁阶段, 当执行beforeDestroy的时候,实例身上所有的data和所有的methods以及过滤器、指令…都处于可用状态,此时,还没有真正执行销毁的过程。
8.destroyed :当执行这个函数的时候,组件已经被完全销毁了,此时,组件中所有的数据,方法,指令,过滤器…都已经不可用了
十一、 过渡类名实现动画
1. vue的内置动画
<style>
.v-enter,
.v-leave-to{
opacity:0;
transform:translateX(150px) --这东西是位移
}
.v-enter-active,
.v-leave-active{
transition:all 0.4s ease;
}
</style>
<transition name='my'>
<h3 v-if="flag"></h3>
</transition>
<script>
data(){
return {
flag:false
}
}
</script>
2. 使用第三方类实现动画
<transition enter-active-class="bounceIn"
leave-avtive-class="bounceOut" duration='200'
>
<h3 v-if="flag" class="animated" ></h3>
</transition>
3. 在属性中声明js钩子 实现半场动画(只需要进场,不需要离场)
<transition
<div
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
>
</div>
</transition>
<transition
<div
v-show="flag"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
>
</div>
</transition>
<script>
methods:{
beforeEnter(el){
//动画入场之前,此时动画尚未开始, 可以在beforeEnter中设置元素开始动画之前的初始位置
el.style.transform=
"translate(0,0)"
},
enter(el,done){
/*这句话,没有实际的作用,但是,如果不写,出不来动画效果,可以认为 这个会强制刷新动画,ofset触发了重绘重排导致动画更新了*/
el.offsetWidth
el.style.transform=
"translate(150px,450px)"
el.style.transition='all 1s ease'
/*这里的done 代表着
afterEnter的引用,
这个会立即执行afterEnter 否则会有延时
*/
done()
},
afterEnter(el){
/*动画完成之后,会调用afterEnter */
this.flag=!this.flag
}
}
</script>
4. 在实现列表过渡的时候,如果需要过渡的元素,是通过v-for循环渲染出来的,不能使用transition包裹,需要使用transitionGroup
<transition-group appear tag='ul'>
<li v-for >
<li>
</transition-group>
.v-enter,
.v-leave-to{
opacity: 0;
transform:translateY(80x);
}
.v-enter-active,
.v-leave-active {
transition: all 0.6s ease;
}
/*离开后下一个东西没有动画使用这个可以使用动画实现下一个东西渐渐地飘上来的效果,要和 v-leave-active的absolute 配合 固定写法*/
.v-move {
transition:all 0.6s ease
}
.v-leave-active{
/* absolute 有个特点元素默认宽度就是最小值,要在元素上添加width:100%*/
position:absolute;
}
<transition mode="out-in">
<component :is="comName" >
</component>
</transition>
tips:
1.v-enter [这是一个时间点] 是进入之前,元素的起始状态,此时还没有开始进入
2.v-leave-to [这是一个时间点] 是动画离开之后,离开的终止状态,此时,元素动画已经结束了
3.v-enter-active[入场动画的时间段]
4.v-leave-active[离场动画的时间段]
5.animated 是个动画库 新版本似乎不需要加入
6.使用:duration=200 来表示动画的时间 如果只写一个表示统一配置了开场和离场时间 用 对象可传入c入场和离场 duration="{enter:200,leave:400}"
7.添加appear属性,实现页面刚展示出来,入场时候的效果
8.通过为transition-group 元素,设置tag属性指定 transition-group 渲染为指定元素,如果不指定tag属性,默认,渲染为span 标签
9.mode=“out-in” 先过渡再进来,防止有 阴影,通过mode`来设置过渡方式。
注意:最外层一定要用transition包裹着,动画似乎升级了,可以在transition标签中加入name属性,并且在css样式中把v,替换为你的name属性值
十二、 组件
1.使用Vue.extend 来创建全局的Vue组件
var coml=Vue.extend({
template:'<h3>这是使用Vue.extend 创建的组件</h3>'
})
//第一个参数组件名称,第二个参数创建出来的组件模板对象
Vue.component('myComl',coml)
<my-coml><my-coml/>
2.使用 vue.component 来创建组件
Vue.component('mycom2',{
template:'<div>
<h3>
这是直接使用Vue.component 创建出来的组件
</h3>
</div>'
})
3.使用 template 来创建组件
<template id='tmp1'>
<div>
<h1>
这里通过template元素,在外部定义的组件结构,这个方式,有代码的智能提示和高量
</h1>
</div>
</template>
Vue.component('mycom3',{
template:'#tem1'
})
4.私有组件 componment
<template id='temp2'>
<h1>这是私有login组件</h1>
</template>
componment:{
login:
{
template:'tmpl2'
}
}
如果使用了Vue.component 定义了全局组件的时候,组件名称使用了驼峰命名,在引用的时候大写的驼峰要改为小写,同时两个单词之间 使用-链接
Vue.component第一个参数:组件的名称,将来在引用组件的时候,就是一个标签形式来引入的,第二个参数:Vue.extend 创建的组件,其中 template就是组件将来要展示的内容
注意:不论是哪种方式创建出来的组件,组件的template 属性指向的模板内容,必须有且只能有唯一的一个根元素。
十三、组件里的data
1.组件可以有自己的data数据
2.组件的data和实例中的data有点不一样,实例中的data 可以为一个对象,但是组件中的data必须是一个方法。
3.组件中的data 除了必须为一个方法之外,这个方法内部,还必须返回一个对象才行。
4.组件中的data数据,使用方式,和实例中的data使用方式完全一样!
5.组件里data为什么必须是个方法返回个对象呢? 因为要确保每个实例里的数据是唯一的,独有的。如果data里的数据是放在实例外部的,会被其他实例共享。
十四、 组件切换
1.组件里的切换 可以用 v-if 和 v-else 进行切换,即标签页切换
<a href=""
@click.prevent="flag=true"
>
登录
</a>
<a href=""
@click.prevent="flag=flase"
>
注册
</a>
<login v-if="flag">
</login>
<register v-else="flag">
</register>
2.vue 提供了 component,来展示对应名称的组件
//component 是一个占位符
:is属性,可以用来指定要展示的组件的名称 写死的时候这个组件名要是个字符串,动态绑定时key普通写法就好,但value必须是字符串。
<component :is="'componentId'">
</component>
<component :is="oneName">
</component>
data(){
return{
oneName:"login",
}
}
十五、父子组件通讯
1.父子组件传值,通过v-bind:(:)来传值,通过props来接收值
2.父组件用事件绑定机制传递方法给子组件—v-on 简写 @
//父组件中
<component-name
:children='children' //传值
@handle='show' //绑定方法
>
</component-name>
data(){
return(){
children:11
}
}
methods:{
show(data){
}
}
3.emit 英文原意: 是触发,调用,发射的意思。
@handle=show 父组件传show方法给子组件。
子组件接收父组件的方法,并用$emit把子组件的值传给父组件
//子组件中
methods:{
handle(){
this.$emit('func',{
age:1,
name:'搞事'
})
}
}
4.在父组件中接收子组件所有参数的同时,添加自定义参数
1.子组件传出单个参数时:
// 子组件
this.$emit('test',this.param)
// 父组件
@test='test($event,userDefined)'
2.子组件传出多个参数时:
// 子组件
this.$emit('test',this.param1,this.param2, this.param3)
// 父组件 arguments 是以数组的形式传入
@test='test(arguments,userDefined)'
tips:子组件中的data数据,并不是通过 父组件传递过来的,而是子组件自身私有的,比如子组件通过ajax,请求回来的数据,都可以放到data身上,data 上的数据都是可读可写的;
十六、 使用 ref 获取dom元素
<h3 id='myh3' ref='myh3'> </h3>
methods:{
getElement(){
console.log( this.$refs.myh3.innerText)
}
}
//组件也可以使用ref,让父组件调用子组件里的方法和属性值
<login ref='mylogin'> </login>
methods:{
getElement(){
//父组件调用子组件里的属性值
console.log(this.$refs.mylogin.msg)
}
}
tips:
1.refs; s代表多个引用,会有多个dom元素。
2.ref英文是reference,值类型和引用类型。
十七、路由
1.这是vue-router提供的元素,专门用来 当作占位符的,将来,路由规则,匹配到的组件,就会展示到这个router-view中去,所以:我们可以把router-view认为是一个占位符
<router-view></router-view>
2.路由切换 模板写法,默认渲染为一个a标签,
使用tag的span可以用来转换模板的标签名
<router-link to="/login" tag='span' >
登录
</router-link>
3.路由配置
new VueRouter({
//路由匹配规则
routes:[
{
path:'/',
redirect:'/login'
},
{
path:'login',
component:login
},
{
path:'/register',
component:register
}
]
//路由高亮的类名
linkActiveClass:'myactive'
})
var vm=new Vue({
el:'#app',
data:{},
methods:{},
router //将路由规则对象注册到vm实例上,用来监听Url地址的变化,然后展示对应的组件。
})
4.路由传参
query
//获取id
this.$route.query.id
在path上设置参数
//参数要一一对应不可缺失,不然可能会
造成路由的不匹配
< router-link
to="/login/12/ls"
>
{
path:'/login/:id/:name',component:login
}
params 新的方式可看文档
5.子路由
<router-link
to="/account/login"
>
</router-link>
routes:[
{
path:'/account',
component:account,
children:{
{
path:'login',
component:login
}
}
}
]
tips:
每个路由规则,都是一个对象,这个规则对象,身上,有两个必须的属性。
属性1 是path,表示监听,哪个路由链接地址;
属性2是component,表示,如果路由是前面匹配到的path,则展示component属性对应的那个组件。
子路由不能加/, 加了/ 会以根目录为基准匹配,这样不方便我们用户去理解url地址
超链接的to 一定要加上父路由
注意:componen属性值,必须是一个组件的模板对象,不能是组件的引用名称
十八、 命名视图实现经典布局
根据name 来找组件
<router-view></router-view>
<router-view name="left"></router-view>
<router-view name="main"></router-view>
var header={
template:'<h1>header</h1>'
}
var leftBox={
template:'<h1>leftBox</h1>'
}
var mainBox={
template:'<h1>mainBox</h1>'
}
{
path:'/',components:{
'default':header,
'left':leftBox,
'main':mainBox
}
}
十九、 watch
监听非dom元素
watch:{
'obj.a'(newValue,oldValue){ },
immediate:false
}
watch:{
'obj':{
handler (newValue, oldValue) {
}
},
deep:true //深程度监听 性能消耗大
}
watch:{
//监听路由
'$route.path':{
handler (newValue, oldValue) {
}
},
//immediate:true代表如果在 wacth 里声明了之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行
immediate:true
}
tips:
1.用了obj.a 加上handle +immediate:true ,就可以监听 对象里的值,如果是obj 加上 handle+deep true 也是可以监听对象的属性但是性能消耗大 一般是直接对象> > +属性
2.用handle 方法可以让watch初始化就执行,如果不用 handle它就先不执行,待数据改变再执行。
3.不要在watch 和computer 中去修改参与计算或者监听的值 而是要生成新的值。
二十、 computed 计算属性
computed:{
'fullname':(){
return
}
}
二十一、 render 函数注册组件(vm[vue实例]的属性)
render:function(createElements){
//createElements是一个方法,调用它,能够把指定的 组件模板 渲染为html结构
return createElements(login)
//注意 这里 return 的结果,会替换页面中el 指定的那个容器
}
tips: render和components区别 render 会把整个app里组件全部覆盖掉一个app中只能放一个render组件components 可以多个,且不会覆盖
二十二、 slot 插槽
1.写插槽
<div v-if="layout === 'block'" class="layout-block" :class="scroll?'layout-scroll':''">
<slot></slot> //匿名插槽
</div>
<!-- 左右块 -->
<div v-if="layout === 'both'" class="d-flex jc-between">
<div class="layout-both" :class="scrollLeft?'layout-scroll':''">
<slot name="left"></slot> //有名字的插槽
</div>
<div class="layout-both" :class="scrollRight?'layout-scroll':''">
<slot name="right"></slot>
</div>
</div>
2.使用插槽
//有名字的插槽 # v-slot的缩写是#
<template #left></template>
<template v-slot="left" > </template>
tips 区别对待v-slot="" 和v-slot:name; =和:的区别 一个是slot的name 一个是父组件获取子组件的数据,插槽一定要用template包裹着
<template>
插槽的内容
</template>
二、杂项
1. nrm
安装 nrm
npm i nrm -g 全局安装
nrm ls 显示列表
nrm use npm 使用npm use 后有很多地址可选择
tips:nrm只是单纯的提供几个常用的下载包url地址,并能够让我们在这几个地址之前,很方便的进行切换,但是,我们每次装包的时候,使用的装包工具,都是npm。
npm i cnpm -g 不一样
2. webpack
在网页中会引用哪些常见的静态资源
js
.js .jsx .coffee .ts(TypeScript)
css
.css .less .sass .scss
Image
.jpg .png .gif .bmp .svg
字体文件(Fonts)
.svg .ttf .eof .woff .woff2
模板文件
.ejs .jade .vue
3. export default 和 export
export default 向外暴露的成员,可以使用任意的变量来接收
在一个模块中,export default只允许向外暴露1次
在一个模块中,可以同时使用 export default 和 export 向外暴露成员
使用 export 向外暴露的成员,只能使用{}的形式来接收,这种形式,叫做[按需导出]
export 可以向外暴露多个成员,同时,如果某些成员,我们在import的时候,不需要,则可以不在 { }中定义
注意使用 export 导出的成员,必须严格按照导出时候的名称,来使用{ } 按需接收
使用 export 导出的成员,如果就想换个名称来接收,可以使用 as 来起别名
const arr={
a:'1',
b:'2'
}
export default arr
/* export default {
这个暴露是错误的所以当前注释 一个js文件中只能暴露一次
address:'北京'
}
*/
export title=1
import arr, {title as title1 } from '/xxx.js'
4. router
render会把el指定的容器中,所有的内容都清空覆盖,所有不要把路由的router-view和router-link 直接写到el所控制的元素中
注意 app这个组件,是通过vm 实例的render 函数,渲染出来的,render函数如果要渲染组件,渲染出来的组件,只能放到el: '#app’所指定的元素中;
Account 和GoodsList 组件,是通过路由匹配监听到的,所以,这两个组件,只能展示到属于路由的
<router-view></router-view>中去
子路由的应用场景在标签页切换
5. scoped原理
样式的 scoped 是通过 css 的属性选择器来实现的 .aa[vsfp]{color:red}
tips:vsfp是哈希值
6. promise
模拟 promise
getFution(aa,callback){
callback(aa)
}
getFution(aa,funtion(res){
console.log (aa)
})
异步操作
/*
每当new一个Promise实例的时候,就会立即执行这个异步操作中的代码。也就是说,new的时候,除了能够得到一个promise实例之外,还会立即调用 我们为 Promise 构造函数传递的那个funtion,执行这个function中的异步操作代码。
可用一个函数包裹,这样就可以不立即执行,用函数执行
*/
var promise=new Promise(function(resolve,reject){
异步操作,ajax函数等,而且可以自由输出东西了
resolve(true)
reject(false)
})
getFunction(){
var promise=new Promise(function(){
异步操作,ajax函数等,而且可以自由输出东西了
})
}
getFunction().then(
function(data){
console.log(err)
},function(err){
console.log(err)
})
正确使用方式
getFunction(aa)
.then(function(data){
console.log(data)
return getFunction() --返回后,可以使用后续的then
})
.then(function(data){
console.log(data)
return getFunction()
})
.then(funtion(data){
console.log(data)
})
//捕获只放在最后面。前面有任何的异常都会终止
.catch(function(data){
console.log(data)
}
tips:在 then里面多写个返回错误的方法是不可取的。
11. vuex
vuex是为了保存组件之间共享数据而诞生的,如果组件之间
有要共享的数据,可以直接挂载到vuex中,而不必通过父子组件之间传值了,如果组件的数据不需要共享,此时,这些不需要共享的私有数据,没有必要放到vuex中;
vuex,存放共享数据,data 存放组件私有的数据 props存放父组件传过来的数据
操作vuex里的state
直接操作store里的属性值,不推荐这种做法
this.$store.state.属性值
推荐只通过mutations 提供的方法,才能操作对应的数据,
mutations:{
increment(state,payload){
state.count++
}
}
this.$store.commit('方法名')
vuex里的getters
如果store中state上的数据,在对外提供的时候,需要做一层包装,那么推荐使用getters。
optCount:state=>state.count
this.$store.getters.***
tips: increment方法里的 state是属于vuex里的state; count是state里的属性 ;payload外部传进来的值,用来修改state里属性的值.。最多支持只能传两个参数,可以是数组和对象。
7. ngrok
可以映射本地80端口,把本地的映射为外网
npm地址
//npm下载 --感觉下的有点慢 换个路径下比较好
npm install ngrok -g
//命令
ngrok http 80
tips: 需要开启本地服务器,映射后只是映射www路径,不是完整的程序路径需要自己去补充完整
9.public
目录下的图片如何用 require引入
//第一种 图片质量小的可以自动转换为base64的
img: require("@/../public/img/home/user.jpg ")
//第二种 这里可以把最前面的 / 看做是public
/img/abnormal/Trash.png
即 public/img/abnormal/Trash.png
tips: @是指src目录 … @的上一级目录,再进入publicz
原文链接:https://blog.youkuaiyun.com/weixin_45418329/article/details/103783507