day01 二阶段的JavaScript开发场景: 1、老公司 2、老项目 3、面试笔试 - js是原理 一切的框架的目的都是为了简化JavaScript:准确来说都是为了简化DOM操作
1、vue介绍:
建数据驱动的web应用开发框架,属于前端框架。(vue几乎不会用DOM操作)
为什么如此受欢迎?
1.声明式渲染,应对前后端分离开发大趋势
2.渐进式框架,适应各种业务需求以及各种场景(从小到大都可以省略)
3.更适合做移动端开发,SPA页面(单页面开发) - 效率更高
4.快速交付,结合第三方UI框架组件库进行快速开发 - 比如elementUI、VantUI
5.企业需求,必备技能(vue,react)
6.中国自己的框架(借鉴了react和angular)
vue是一个属于mvvm架构的框架:什么是mvvm?
m - model:模型数据
v - view:视图
vm - ViewModel控制器
我们一般都统称为mv*架构:mvc、mvp、mvvm
开发环境搭建:两种方式
1、下载引入:vue.js
2、vue-cli - 脚手架 - 新手不推荐
2、vue开发模板
new Vue({
el:"#box",//只有在id为box的div里才可以使用vue的语法
data:{//这里面放的是变量
变量名: 值,
},
methods:{//这里面放的是函数
函数名(){
操作
},
}
})
3、插值表达式:{{变量}} - 再HTML上实现了一个基本的js环境,可以进行js运算、放入变量、三目运算、API操作...
4、vue的指令:再HTML上写着v-xxx的特殊属性
v-html:底层就是innerHTML,做了简化操作,可以渲染标签,其实就是添加了内容
比如:<elem v-html="变量"></elem>
v-for:底层就是for in循环,做了简化操作,可以遍历数组
比如:<elem v-for="(v,i) in 数组名">{{v}}</elem> - 会根据数组渲染出多个元素,拥有下标和值
注意:()写不写都无所谓
v-modal:具有双向数据绑定功能,页面可以控制变量,变量也可以控制页面
比如:<input v-modal="变量名"> - input的默认值就为此变量,并且input修改内容,变量也会跟着一起变化
v-show:隐藏和显示,传入的是一个布尔值,根据你的布尔值进行显示隐藏,如果为true则显示,如果为false则隐藏,底层:设置display为none/block
v-if:是否渲染页面,传入的是一个布尔值,根据你的布尔值进行显示隐藏,如果为true则显示,如果为false则隐藏,底层:appendChild/remove
比如:<elem v-show/if="布尔值"></elem>
v-bind:属性名 - 操作动态的属性:简写为:属性名
<a :class="变量" :href="变量"></a>
v-on:事件名 - 绑定事件,简写为:@事件名="函数名"
<a @事件名="函数名"></a>
5、vue2的操作样式
1、class操作样式:
<div :class="obj">文字</div> - 对象口味的语法糖通过下方代码,最终class有aa和bb为true,则带有此class,cc为false说明不需要
<div :class="arr">文字</div> - 数组口味的语法糖通过下方代码,最终class有aa和cc
new Vue({
el:"#box",
data:{
obj:{ - 样式class对象口味写法
aa:true,
bb:true,
cc:false, - 注意后续不能用js直接添加dd,不能直接追加新属性和值,vue底层具有拦截机制,想要添加:Vue.set(vm对象.obj,"dd",true);
},
arr:["aa","cc"] - 样式class数组口味写法,可以随便的添加和删除,更加的随意简单:vm对象.arr.push("dd");
},
methods:{
}
})
2、style内联样式操作
<div :style="obj">文字</div> - 对象口味的语法糖通过下方代码,最终style内联样式,要有的内容需要搭配下面的代码
<div :style="arr">文字</div> - 数组口味的语法糖通过下方代码,最终style内联样式
var vm=new Vue({
el:"#box",
data:{
obj:{
background:"red",
width:"300px",
height:"300px",
border:"1px solid #000",
borderRadius:"50%",
overflow:"hidden" - 注意后续不能用js直接添加新样式,不能直接追加新属性和值,vue底层具有拦截机制,想要添加:Vue.set(vm对象.obj,"css属性名","css属性值");
},
arr:[
{background:"red",},
{width:"300px",},
{height:"300px",},
{border:"1px solid #000",},
{borderRadius:"50%",},
{overflow:"hidden"}, - 样式class数组口味写法,可以随便的添加和删除,更加的随意简单:vm对象.arr.push({"属性名","属性值"});
]
},
methods:{
}
})
6、vue3的操作样式:
1、模板写法就不一样
Vue.createApp({
data(){
return {
变量名:值,
}
},
}).mount("#box");
2、反而vue3操作样式不用担心vue2的问题,之前的注意点就可以忽视了,对象可以直接用老JS语法添加属性了
7、条件渲染:就是v-if的升级版
<ul>
<li v-for="v in datalist">{{v.name}} -
<span v-if="v.state===0">未付款</span>
<span v-else-if="v.state===1">待发货</span>
<span v-else-if="v.state===2">已发货</span>
<span v-else>已完成</span>
</li>
</ul>
通过这些代码,我们可以实现根据json数据渲染页面,并且判断状态的不同显示不同的span文字
8、列表渲染:
1、v-for:遍历数组、遍历、甚至是一个数字
<ul>
<li v-for="v in 数据名" :key="v.id">{{v}}</li> - 遍历数字基本没有意义,不管是遍历对象还是数组,前面始终是值,后面始终是下标
</ul>
2、虚拟DOM:数据->vue变为虚拟DOM:JS对象描述的一个节点,然后在和真实DOM进行比较,考虑要不要替换真实DOM->真实DOM
新的数据会生成新的虚拟DOM,然后VUE底层会使用diff算法拿着新的虚拟DOM和老的对象,找不同
找到不同后,会更新出一个补丁,渲染到真实DOM之中,这样的好处就是代价更小(性能)
为什么说虚拟DOM代家更小呢,因为真实DOM非常复杂,有很多很多的属性,但是虚拟DOM只需要重要的属性就够了
理想情况:key="v.id",千万不要用下标当做key
目的:高效复用DOM
面试题:为什么li要添加key?
3、数组更新检查:
1、以下方法操作数组,可以检测变动:- 强烈推荐
push/pop/unshift/shift/splice/sort/reverse
2、filter/concat/slice/map - 不会修改原数组,会返回一个新数组,我们可以用新数组再去【覆盖】原数组 - 一般般
3、不能和检测以下变动的数组
arr[下标]=新值;
但是vue3不必担心此问题:已解决
day002
1.事件处理器:
绑定事件指令:@事件名="函数名()";
特殊:1、函数名的(),如果不传参数,其实可以省略
2、如果调用时,没有加(),我们的函数甚至会自动获得一个形参 - event对象
3、如果调用时,希望能使用event对象,又想传入自己的实参,那么你必须写为
@事件名="函数名($event,实参1,实参2,...)"; - 强调:$event名字不能变!
案例:点击一个按钮,使页面上的一个数字+1
2、事件修饰符:
@事件名.stop="函数名()"; - 阻止冒泡
@事件名.self="函数名()"; - 只有点击自己才会触发
@事件名.prevent="函数名()"; - 阻止默认行为
甚至按键修饰符:
@keydown.enter="函数名()" - 只有回车键才会触发
@keydown.ctrl="函数名()" - 只有回车键才会触发
除了这两个,还有很多:.esc .up .down .left .right .space .shift .delete,甚至还可以组合使用,甚至还可以.键码
都是简化event
3、表单控件绑定
1、多选框:想要知道选中没有,现在非常简单
<input type="checkbox" v-model="变量">
变量值要求必须是一个布尔值,如果为true则为选中,false则为不选
2、如果多个多选框,希望判断选中否
<input type="checkbox" v-model="变量" value="值1">
<input type="checkbox" v-model="变量" value="值2">
<input type="checkbox" v-model="变量" value="值3">
此时的变量需要保存的是一个数组,数组根据传入的value,让对应的多选框勾选成功
3、单选框:判断选中谁
<input type="radio" v-model="变量" value="值1">男
<input type="radio" v-model="变量" value="值2">女
勾选中,此变量会自动保存单选框的value值
切记:1、单选框和多选框不要使用点击事件,否则时机不对(得到点击之前的东西),需要使用change事件
2、数据驱动页面
4、表单修饰符:
v-model.lazy="变量" - lazy懒惰,只会在失去焦点时获取到用户输入的内容,提升性能
v-model.number="变量" - 自动隐式转换为数字的操作
v-model.trim="变量" - 自动去掉字符串开头结尾的空白字符
4、计算属性
var vm=new Vue({
el:"",//挂载页面元素
data:{},//模型数据
methods:{},//放函数
computed:{
函数名(){
return 结果;//注意此部分叫做计算属性,很像一个函数,但是必须加return返回值,而且在使用时不能加()调用
//虽然看上去更加麻烦了,但是js中就应该放入逻辑,HTML上不推荐
//但是methods调用几次就会执行几次,但是computed调用多次只要数据不变的情况下只会执行一次
//methods可以说是专门为事件准备的,computed不能绑定在事件上,那他用来干什么?
//只要以后有跟计算相关的都放到computed里面 - 【重在结果】
}
},
})
5、监听属性:
var vm=new Vue({
el:"",//挂在页面元素
data:{},//模型数据
methods:{},//放函数
computed:{},
watch:{
变量名(new,old){//监听,能时刻监听到数据的变化,甚至是异步数据,比如:input不需要再用@input事件了
}
}
})
方法methods->事件绑定,不可以用return 计算computed->重视结果,解决模板过重的问题,必须要有return,只求结果,不支持异步,只能同步! 监听watch->重视过程,监听一个值的改变,不用返回值,支持异步的
1、fetch:ES6提供的一个新功能,类似于ajax - 是标准方法
以前原生ajax,是一个设计粗糙的API,配置和调用方式非常繁琐
而且基于事件的异步模型写起来不友好
fetch缺点:兼容性不好,我们可以用caniuse.com这个网站看看哪些技术支持哪些浏览器
语法:
1、fetch - get
fetch("路径.json").then((res)=>res.json()).then((res)=>{
res要干什么操作
})
2、fetch - post
fetch("路径.json",{
method:"POST",
headers:{
"Content-Type":"application/x-www-form-urlencoded"
},
body:"name=dy&pwd=123123"
}).then((res)=>res.json()).then((res)=>{
res要干什么操作
})
2、axios:是一个第三方的请求方式,但是比fetch更简单更好用,而且vue作者也非常推荐
1、记得先引入,后使用
语法:
1、get方式
axios.get("路径.json","请求消息").then(res=>{
res.data->拿到数据
})
2、post方式:
axios.post("路径.json","请求消息").then(res=>{
res.data->拿到数据
})
day003
组件:组成页面一部分的部件比如:导航条,轮播,侧边栏,底部,抽屉
1.为什么组件化:
vue强烈推荐组件化思想:拓展HTML元素(自定义标签),封装可以【重用】的代码
2.组件的创建/注册方式
1、全局/局部组件
//全局组件
Vue.component("全局组件名",{
template:"<div css/js>内容
<局部组件名></局部组件名>
</div>", - html模板
data(){return {}},
methods:{},
...//之前的模板语法都是支持的,但是data必须写为函数式写法,vue3的语法
components:{//局部组件
"局部组件名":{
套娃
}
}
})
//以前这个new Vue({})我们可以看作是一个根组件
使用:在HTML直接写双标签,你的组件名就是标签名:<全局组件名></全局组件名>
注意:1、起名字,如果js写驼峰,html不支持,必须替换写为横线连接符-
2、html片段,没有代码提示,没有高亮显示,但是不担心 - 以后vue单文件组件解决
3、css只能写成内联样式 - 以后vue单文件组件解决
4、template只能包含一个根节点
5、组件是一座孤岛,无法直接访问外面的组件的状态和方法 - 需要使用间接的组件通信才可以解决
6、data必须写为函数时写法,vue3的语法
7、所有的组件都放在一起的话,太乱了太丑了 - 以后vue单文件组件解决
何时使用全局或局部:
1、如果一个组件只会使用过一次推荐定义为局部
2、如果一个组件在不同的页面或者各个组件中都会使用到,推荐全局
3、组件通信-父传子:提升组件的复用性
比如:一个网页上任何一个页面都有一个导航条,但是显示效果可能不同,我们也可以实现一个组件,传入不同的参数进行通信
<div id="box">
<paoge-navbar></paoge-navbar>
<paoge-navbar 自定义属性="值/根组件的变量"></paoge-navbar> - 自定义属性用来进行传参
</div>
Vue.component("paogeNavbar",{
template:`<div style="background:red;">
<button v-show="bool"><</button>
<span>{{自定义属性}}</span>
<button>></button>
</div>`,
//props:["自定义属性",...],//第一种写法 数组语法糖
props:{//第2种写法 对象语法糖
自定义属性:{
type:String/Number/Boolean,
default:"默认值,不传自定义属性的时候使用的"
}
},
}
4、组件通信-子传父:但是封装了组建后,完成开关门
<div id="box">
<navbar @自定义事件名="爸爸的函数名"></navbar>
</div>
Vue.component("navbar",{
template:`
<div style="background: red;">
<button @click="change">三</button>
导航条
</div>
,
methods:{
change(){
this.$emit("自定义事件名");
}
}
})
//一个页面只能有一个这个【根组件】
new Vue({
el:"#box",
data:{
bool:true,
},
methods:{
爸爸的函数名(){
console.log("父组件定义的事件,操作");
}
}
})
//总结:
父传子 - 用自定义属性搭配props
子传父 - 用自定义事件搭配this.$emit("自定义事件名")
5、非父子关系通信
bus:中央事件总线,实现较为复杂的通信
创建:var bus=new Vue();
方法:2个:使用前,考虑清楚谁是发布者,谁是订阅者,订阅者需要使用生命周期mounted来触发 - dom渲染完毕后
1、订阅者:
bus.$on("自定义名称",(data)=>{
data->下方发布者传输的数据
})
2、发布者:
bus.$emit("自定义名称",传输的数据);
6、refs:父组件可以随意的摆弄子组件(获取/修改)
ref - 绑定在dom节点上,拿到的就是这个dom对象
ref - 绑定在组件上,拿到的就是当前组件对象
<组件 ref="自定义名称"></组件>
根组件中:
this.$refs - 得到所有添加了ref属性的组件对象
this.$refs.自定义名称 - 拿到某个子组件对象
this.$refs.自定义名称.变量 - 拿到某个子组件对象上的变量
组件注意:
1、ref和refs是固定关键字,不能修改
2、他打破了传统的通信流程,比如我们想要获取一个input的value值,再vue中可以用v-model,确实很棒,但是react中没有,则可以使用ref完成
3、尽量不要使用组件中的props去改变状态data,会导致数据流混乱(不易读) - 不推荐,也没有意义
4、如果组件中写了一个指令v-once,一次性的,状态改变,页面上的组件也不会变化,只需要打开页面渲染一次时
5、内置组件:
<component :is="组件名"></component> - 告诉他哪个需要显示
<keep-alive></keep-alive> - 活着,就算选项卡切换,回来依然存在你输入的东西
以上包含了组建的通信,都要一个给,一个拿
面试题:Vue组件的通信有哪些方式?
1、父传子 - 用props自定义
2、子传父 - 用this.$emit("自定义事件")
3、兄弟:中间人模式
4、bus
5、refs
6、vuex - 状态管理器,最舒服,Vue由三部分组成:vue基础+vue router+vuex
day004
1、slot:插槽,组件标签中默认是不允许再嵌套别的标签的,所有提供了slot扩展组件能力,提高了组件的复用性
比如:
<组件>
<template v-slot:名字>
<span>111111111</span>
<span>222222222</span>
<span>333333333</span>
<template>
<template>
<span>777777777</span>
<span>888888888</span>
<span>999999999</span>
<template>
<span slot="user">个人中心</span>
<span>111111111</span>
<span>222222222</span>
<span>333333333</span>
<span>777777777</span>
<span>888888888</span>
<span>999999999</span>
</组件>
默认是不允许再嵌套别的标签的,但是搭配上slot就可以了,以下代码教你如何搭配
Vue.component("组件",{
template:`
<div>
<span>navbar</span>
<slot name="user"></slot> - 用上你写的<span slot="user">个人中心</span>
<slot></slot> - 用上所有没有名字的slot
</div>
`
})
2、过渡:添加动画
语法:
<transition enter-active-class="开始动画的class" leave-active-class="离开动画的class">
<div v-show="isShow">11111111111111111111111</div>
</transition>
<transition name="class的前缀">
<div v-show="isShow">11111111111111111111111</div>
</transition>
注意:
1、如果希望一打开页面就有一次动画,可以在transition标签上添加一个appear
2、如果多个元素过渡,别用v-show,使用v-if v-else
<transition name="paoge" mode="out-in">
<div v-if="isShow" key="1">11111111111111111111111</div>
<div v-else key="2">22222222222222222222222</div>
</transition>
3、多个组件实现过渡,同上
<transition name="paoge" mode="out-in">
<component :is="变量"><component>
</transition>
4、列表ul li过度
<transition-group name="paoge" tag="ul">
<li v-for="(v,i) in arr" :key="v">
{{v}} - <button @click="del(i)">x</button>
</li>
</transition>
3、组件的生命周期:一共8个,4组,自动再不同的时刻自动触发,没写则不行
面试中:问vue的生命周期、组件的生命周期、组件的钩子函数、组件的生命周期钩子函数,都是在问同一个问题
new Vue({
data:{},
beforeCreate(){
//没用
},
*created(){
发起ajax
},
beforeMount(){
},
*mounted(){
发起ajax、找到dom后触发js操作(swiper自己的js应该再此处执行)
},
beforeUpdate(){
},
*updated(){
},
beforeDestroy(){////没用
console.log("清除定时器,事件解绑")
},
Destroyed(){////没用
console.log("清除定时器,事件解绑")
}
})
4、swiper:www.swiper.com.cn/usage/index…
day005
1、Vue3组件的定义:
var obj={
data(){
return {
}
},
methods:{},
...
}
var app=Vue.createApp(obj);
app.component("组件名",{
template:`<root></root>`
})
app.mount("#box");
注意:Vue3除了语法不同,生命周期中的两个销毁也不同:beforeUnmount、unmounted
2、自定义指令:为了操作底层dom,作者给我们留了方案,我么们可以自定义指令
何时:可以通过指令知道什么时候dom创建完成,从而进行以来都dom的库(swiper)的初始化操作(new Swiper)
创建指令:
Vue.directivee("指令名别加v-",{
//指令的生命周期
inserted(el,binding){
el->当前使用此指令的元素
binding->对象,binding.value->拿到用户传给我们的数据
},
mounted(el,binding){
el->当前使用此指令的元素
binding->对象,binding.value->拿到用户传给我们的数据
},
update(el){
el->当前使用此指令的元素
binding->对象,binding.value->拿到用户传给我们的数据
}
})
简化:
Vue.directivee("指令名别加v-",(el,binding)=>{
el->当前使用此指令的元素
binding->对象,binding.value->拿到用户传给我们的数据
})
注意:1、vue3的指令的生命周期 变化了, 约等于 组件的生命周期
2、this.$nextTick(()=>{
比updated执行的都要晚,new Swiper(".swiper",{})
})