https://cn.vuejs.org/
在官网的教程中有安装,点击会下载vue.js文件。下载后在HTML页面中引入即可。
引入之后打开页面显示如下,安装扩展vue开发者工具,
百度网盘,提取码6666
输入vue如下图显示为正常。
关闭上图红色框中的提示信息:
Vue.config.productionTip = false;
返回一个索引,不包含返回-1。
所有字符串都包含空字符串’',其索引为0.
在生命周期函数加入以下语句,页面在浏览器打开,打开控制台,语句会在断点处卡住。
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
返回一个bool值。
数组有多长就调用reduce多少次,两个参数分别是上一次调用reduce的返回值和数组元素,第一次调用reduce的pre是0,后面逗号后的0是初始值。
最后一次调用的返回值将作为reduce的返回值。
不管传过来多少个参数,只接收第一个,其他的保存在params
数组里面。
例如下面第一个参数是不使用的,可用_
占位,避免变量不使用的警告。
例:todo_list案例中编辑功能,点击编辑input获得焦点。如果不使用$nextTick,由于执行完handleEdit
中代码再更新DOM,input并不会获得焦点。
此处也可以使用定时器,并且不给时间,由于定时器会推到队列中执行,input获得焦点将在更新DOM之后。
欲要将 dataObj 对象中的数据赋给 this.info 对象,使用下面的方法,将对象的元素摊开,如果 this.info 中有而 dataObj 中没有,会保留,如果两者都有则替换,如果只有 dataObj 有则添加。
####2.14.vue项目main.js代码的执行顺序
先执行完所有 import 语句再执行其他。
传入对象,返回属性名
var data={a:1,b:2,c:9,d:4,e:5};
console.log(Object.keys(data));//["a", "b", "c", "d", "e"]
Object.keys(data).map((key,item)=>{
console.log(key,data[key]);//key=>属性名 data[key]=>属性值
});
传入字符串,返回索引
var str = 'ab1234';
console.log(Object.keys(obj)); //[0,1,2,3,4,5]
传入数组 返回索引
var arr = ["a", "b", "c"];
console.log(Object.keys(arr)); // console: ["0", "1", "2"]
map的返回值为一个数组,数组的内容由回调函数确定。
map的参数为一个有返回值的回调函数,返回值即为map函数将要返回的数组的元素。
var arr = [1,2,3,4,5]
var doubleNumber = arr.map(function(num){
return num*2
})
console.log(doubleNumber) //[2,4,6,8,10]
在vscode安装live server插件。
将图标加入到项目文件夹下。
使用live插件打开。
<body>
<div id="root">
<h1>hello ,{{name}}</h1>
</div>
<script>
Vue.config.productionTip = false;
// 创建vue实例
const x = new Vue({
el: '#root',//和容器建立关系,通常为css选择器
// el:document.querySelector('#root');另一种写法
data: {//data中的数据给el元素使用
name: '尚硅谷'
}
});
</script>
</body>
单项数据绑定(简写为:)
Vue中有2种数据绑定的方式:
1.单向绑定(v-bind):数据只能从data流向页面。
2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
备注:
1.双向绑定一般都应用在表单类元素上(如:input、select等有value属性的值)
2.v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。
相比于直接在对象中写属性,Object.defineproperty()给对象添加的属性可以添加很多限制,例如增删改的限制。
也可以这样
需要传参数可在函数名后加括号和参数。不写$event是没有event事件的
捕获到就触发事件而不等到冒泡再触发。
箭头函数this不指向vue实例而是指向window。
滚动条发生变化时触发
鼠标滚轮滚动时触发
自定义键盘事件
示例
按下Ctrl+y生效:@keydown.ctrl.y
vue的data里面的内容就是这里说的属性。
计算属性在computed里面,每个属性写成一个对象。虽然写成一个对象,但存到vm的是计算好的属性,而不是一个对象。
使用时也是使用插值语法。
案例:以下的fullName是一个计算属性,使用属性经过计算的到的,使用get监听,一旦其依赖的属性发生改变,fullName也将改变。
缓存:多次读取 fullName,第一次读取会计算 fullName,之后的读取都是读取缓存,fullName发生改变将更新缓存,因此缓存始终与最新的fullName保持一致。
不能开启异步任务,例如定时器,因为需要返回一个值,而使用定时器返回值将返回给定时器,而不返回给计算属性。
而监视属性可以,因为监视属性不靠返回值实现修改fullName的值。
配置方式和计算属性相似。
计算属性也能监视。
一定要使用箭头函数,因为定时器的回调不是属于vue管理的,而属于js引擎。不使用箭头函数this将指向window。
而箭头函数没有自己的this,因此this还是指向vue实例。
对象要使用驼峰命名。
如果有多个样式对象,可以将多个样式对象放在一个数组里给style。这个办法不常用。
为true时显示,为false时隐藏。
两者值为false时都会把标签隐藏,区别是v-show会display:none,v-if会直接删除元素。置为 true时v-show会display:block,而v-if会添加一个元素。
切换频率高用v-show,频率低用v-if。
从上往下判断条件,找到符合条件的后就不再往下找了。
这几个要连着写,以下情况是不行的
使用场景,几个h2标签的判断条件相同,不用写三个v-if。这样写之后页面渲染时会把template标签去掉,保留三个h2标签,同时保留v-if的效果。
template不能和v-show配合使用。
v-for和key。v-for写在谁身上就遍历谁。
使用index作为key会出现问题。
出现的问题
关键是虚拟DOM对比这一步。
使用id作为key就不会出现这种问题,
搜索名字案例:
监视属性实现。
出现的问题。
updateMei绑定在一个按钮上,但是点击按钮列表没有改变。
原因,直接修改数组元素,vue是监测不到的,要使用vue提供的方法对数组进行操作。
vue对数组元素的监测是通过包装数组的方法实现的,实现基本功能的同时加入了重新解析模板的步骤,将触发视图更新。包装的方法有以下几个。
也可以使用vm.set(persons,0,{id:'001',name:'马老师',age:50,sex:'男'})
将把数组persons索引为0的元素替换。vue可以监测到并会重新解析模板、触发视图更新。
对对象的监测是通过分配getter和setter实现的。
v-model.trim用于去掉输入框内首尾空格。
v-model.number将用户的输入值转为数值类型
v-model.lazy当input框失去焦点时触发事件,vue更新读取到的数据。
使用如下代码获得input框的value
<template>
<div class="todo-header">
<input type="text" @keyup.enter="add"/>
</div>
</template>
<script>
export default {
name: "MyHeader",
methods: {
add(event) {
console.log(event.target.value);
},
},
};
</script>
过滤器不写括号也会传入参数,参数为value,多个参数时value是第一个参数。
可以用在插值语法(常用)和v-bind(罕见),其他不可用
dayjs是一个格式化时间戳的库(插件),可以在bootcdn官网查看和下载。
局部过滤器,只有vm绑定的元素可用:
<!-- 过滤器实现(不传参) -->
<h3>现在是:{{time | timeFormater}}</h3>
<!-- 过滤器实现(传参) -->
<h3>现在是:{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>//有多个过滤器时从做到右执行
<h3 :x="msg | mySlice">尚硅谷</h3>
filters:{
timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){//如果不传入str参数,默认为str='YYYY年MM月DD日 HH:mm:ss'
return dayjs(value).format(str)
},
mySlice(value){
return value.slice(0,4)
}
}
向其所在的标签添加文本。添加的文本会覆盖标签原有的内容。
不能添加标签,会解析成文本。
只有名没有值。
解决网速慢未经解析模板显示问题。当vue.js加载完接管容器之后这个v-cloak会被移除。
将标签作为普通标签,不会解析vue语法,直接渲染。加快编译。
使用配置项 directives 。
使用函数的方式定义指令,big()两个参数分别是操作的元素和big指令这个对象,其中big对象的value是n的值。
v-big何时被调用?
使用对象式定义。
以下代码不好使,因为指令执行时模板还未渲染到页面,因此当页面显示时input框并未获得焦点。
如何解决?当vue把元素放入页面之后给input框焦点。此处就要使用对象式定义了。
对象式中可以写成很多个函数的形式,
指令内vue根据不同时间节点提供了不同函数可以在不同时间节点做不同的事。不同函数都能收到两个参数,即element元素和binding绑定对象。
函数式相当于只有bind和update而没有 inserted,因为bind一般和update相同。
实现上述功能。
(1)命名:使用时多个单词用 -
分隔。定义时多个单词还用 -
分隔,但是要加 ''
。一个单词可以简写不用''
。
(2)directives 里面的函数的this指向window。
概念:在vue实例的不同时间节点调用的函数。
vue的生命周期流程图
红色框内是不同时间节点的生命周期函数名。
vue将初始的真实DOM第一次挂载到页面上之后。只调用一次。
不会因为模板再次解析而被重复调用。
组件:用来实现局部功能效果的代码集合。
缺点:样式不能写在组件里面。
(1)创建组件
不能写el,data要写成函数形式。
(2)注册组件
局部注册
注册组件,全局注册
所有vue实例都能用。
(3)使用组件,编写组件标签
(1)可以写多个相同组件标签,即可以复用。
(2)组件改变不会影响其他组件
(3)组件的命名
单个单词:建议全部小写,也可以首字母大写,开发者工具中呈现的都是首字母大写的形式。
多个单词:官方推荐单词间使用-
连接,外加''
,
开发者工具显示是这样的
第二种书写方式是直接连接,首字母全部大写,需要在脚手架里面使用,否则会报错。
(4)在定义组件时添加配置项name
指定开发者工具中组件的名称,首字母还是会自动大写。
注册的组件名称不会改变,引用的组件标签也不会改变。
School.vue
<template>
<div class="demo">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我提示学校名</button>
</div>
</template>
<script>
export default {
name:'School',
data(){
return {
name:'尚硅谷',
address:'北京昌平'
}
},
methods: {
showName(){
alert(this.name)
}
},
}
</script>
<style>
.demo{
background-color: orange;
}
</style>
App.vue
<template>
<div>
<School></School>
<Student></Student>
</div>
</template>
<script>
//引入组件
import School from "./School.vue";
// import Student from "./Student.vue";
export default {
name: "App",
components: {
School,
Student,
},
};
</script>
main.js作为入口文件
import App from './App.vue'
new Vue({
el:'#root',
template:` `,
components:{App},
})
html页面,包含容器
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>练习一下单文件组件的语法</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="root"></div>
<!-- <script type="text/javascript" src="../js/vue.js"></script> -->
<!-- <script type="text/javascript" src="./main.js"></script> -->
</body>
</html>
(1)打开cmd。
(2)使用淘宝镜像源
npm config set registry https://registry.npm.taobao.org
(3)全局安装
npm install -g @vue/cli
(4)切换到要创建项目的目录,然后使用命令创建项目
vue create vue_test
vue_test为项目名
(5)启动项目
cd vue_test
进入项目所在目录。
npm run serve
render用于渲染使用精简版vue的页面,使用精简版vue空间小但是没有模板解析器,不能渲染 template 模板,不能使用 template 配置项。
只有创建 vm 的时候需要使用render,其他vue文件中的template还是可以使用。
下面的语句是引入组件和创建一个h1
标签需要两个参数,分别为标签类型和内容。
props接收的数据不建议更改。
Student.vue接收App.vue传过来的数据作为自己的数据。
App.vue传数据给子组件
Student.vue限制接收的数据的类型,age仍然可以接收string但是会输出警告提示。
最完整的接收配置项
如何修改props接收到的数据?不直接使用props接收到的数据,复制一个到data中,修改data中的数据。
可以将公共的配置项放入混合里面,复用配置,减少组件的代码量。
混合是一个.js
文件,里面可以放各种配置。
引入混合(局部混合)
注意点:
如果配置项在混合里面和组件的配置项里面都存在,会进行整合,如果冲突则以组件的配置项为准。
对于生命周期钩子,如果冲突则两者都要,混合的在前。
插件放在一个.js
文件中,方法定义在install里面,install接收到的第一个参数是Vue的构造函数。
当不同组件类名相同时采用后来居上的策略,加上scoped之后限制样式的作用域为本组件,不会影响其他组件。
自定义事件也可以使用事件修饰符。
实现子组件向父组件传递数据的自定义事件。
第一种绑定方式:
下面代码在vc
实例对象student
上绑定了atguigu
事件,当atguigu
事件触发时调用getStudentName
函数。
简写形式,将v-on:
换成@
。
第二种绑定自定义事件的方式:
这种方式更加灵活,可以设置定时器。
首先给student
一个ref
标识。
在Student
组件设置触发atguigu
事件的方式,并将所需的数据,即name
作为事件的参数,getStudentName
作为atguigu
事件的回调将收到atguigu
事件传回的参数。因此完成了子组件向父组件传递数据。
解绑自定义事件:
销毁组件实例后,自定义事件将失效。原生事件将不受影响。
MyFooter
是一个组件标签,下面代码并不能给组件绑定一个原生的click
事件,vue将其解析为自定义事件。
<MyFooter @click="demo"/>
以下代码会将click
解析为原生事件,绑定在组件的根元素,需要加native
事件修饰符。
<MyFooter @click.native="demo"/>
核心思想是在vue
原型对象上绑定一个vue
实例对象,该vue
实例对象可以和各个组件通信,通过自定义事件的方式传输数据。
注意是 $bus
上的$emit
。
School
组件绑定事件。
School
组件销毁的时候解绑事件。
student
去触发hello
事件,hello
事件的回调函数将数据接收,School
组件就接收到数据了。
消息订阅与发布。
安装插件:
npm i pubsub-js
发送方:hello
是消息名,发送方与接收方应保持一致,666
是发送的消息。
接收方订阅消息
组件化编程,使用了很多小技巧。
使用了本地存储。
使用了自定义事件实现 数据子组件=>父组件
。
使用全局事件总线实现 数据子组件的子组件=>父组件
。
localStorage,刷新页面还存在,不清空缓存会始终存在。
当读取的内容不存在时读取到的是null而不是undefined。
sessionStorage 的api和localStorage 的 api 相同,但是sessionStorage 刷新后会消失。
在css3中写动画
vue用transition
将要添加动画效果的标签包含起来,渲染的时候transition
会被去掉,和template
一样。
其中hello
是动画名,appear
属性默认为true
,页面加载完就有动画。
需要使用transition-group
包含,且为每个元素设置一个独一无二的key
。
https://www.npmjs.com/package/animate.css
查看动画示例
https://animate.style/
在终端安装
npm install animate.css
animate__animated animate__bounce
引入axios
npm i axios
使用axios发送get请求
解决跨域问题需要后端人员配置cors
头部信息。
还可以使用代理服务器,前端和代理服务器交互,而代理服务器与目标服务器交互,因为服务器之间不会收到跨域的限制,因此可以解决跨域问题。
需要编辑配置项,而修改配置文件 vue.config.js
需要重启脚手架才会生效。
这种方式只能开启一个代理服务器,且会有一个问题。
代理服务器和前端页面的URL是相同的。此处都为http://localhost:8080
目标服务器的地址:http://localhost:5000/students
在vue.config.js
中添加如下代码,注意5000
这个端口是目标服务器的端口。
devServer:{
proxy:‘http://localhost:5000’
}
一个代理服务器就开启了。
将axios.get
请求URL的端口号调整为 8080
解决了跨域问题
注意:
axios.get 请求发送给代理服务器,当代理服务器中有所请求的数据时将直接返回数据,而不会去请求目标服务器。
例如请求http://localhost:8080/students
,如果public中有students,将直接返回,不再访问目标服务器。
代理服务器拥有的数据是 public 中的数据。
可配置多个代理服务器。
同样在 vue.config.js 添加代码,以下代码中的/atguigu
是前缀,发送请求时在端口号后添加前缀,将不使用代理服务器的数据,代理服务器会将请求发给目标服务器。
devServer: {
proxy: {
'/atguigu': {
target: 'http://localhost:5000',
},
}
}
以下请求将 404
原因如下,代理服务器请求的是 /atguigu 下的 /students ,因此是 404 。
如何解决?添加一个配置项 pathRewrite
其他配置项:
ws项用于支持websocket
changeOrigin为true时,代理服务器将告诉目标服务器自己的端口号和它一样,即5000;为 false 时将如实告知目标服务器 自己的端口号为 8080 。这个配置项不写默认为 true 。
./foo是另一个代理服务器。
所有组件都会多一个 $http
安装:npm i vue-resource
引入:
使用:
和axios
差不多,把axios
替换成this.$http
即可
插槽的样式可以写在 app.vue ,也可以写在 Category.vue ,app.vue 解析完DOM之后才传给 Category.vue 。
在 app.vue 的组件标签中填入红色框中内容,作为插槽的使用者。
对应的组件用 slot 接收 app.vue 传过来的内容,slot用于确定传过来的内容的位置。
如果没有传过来内容,则显示 slot 标签的内容。
插槽的提供者。
组件标签中的元素加上slot属性,值为slot的name,就可指定元素的插槽。如下代码 img 将放在 name="center"
的插槽。
可以使用 template 临时标签
插槽的使用者要使用的数据在插槽所在的组件。
插槽的提供者:
插槽的使用者:
接收插槽提供者的数据,需要配置 scope
属性,名字可随意起,作为接收数据的对象,之后就可以使用插槽提供者的数据了。
可以传多个数据
vuex作为中间人,可以和任意组件通信,将数组存在vuex的state中,任何组件都能使用。
案例
vue2 中只能使用 vuex3 ,vue3 用 vuex 4。
安装vuex,npm i vuex@3
。
引入vuex,import Vuex from 'vuex'
Vue.use(Vuex)
。
创建store:
创建文件 src/store/index.js
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions对象——响应组件中用户的动作
const actions = {}
//准备mutations对象——修改state中的数据
const mutations = {}
//准备state对象——保存具体的数据
const state = {}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
在main.js中创建vm时传入store配置项
......
//引入store
import store from './store'
......
//创建vm
new Vue({
el:'#app',
render: h => h(App),
store
})
在 Count.vue
中要使用 存在 store
中的 sum
。
Count.vue
使用 this.$store.dispatch("jia", this.n);
告诉store
要执行的操作为jia
,具体的操作在store
中定义。
store
在 actions
中定义 jia
这个动作,并将之提交给 mutations
。业务逻辑都写在 actions
里面,包括判断、定时器等。
mutations
中真正定义了jia
具体的操作。
actions 中的context是低配版的 store ,可以调用commit 将动作提交给 mutations ,也可以读取到 state 中的数据,还可以写业务逻辑,即判断、定时器等。
如果没有业务逻辑也没有特殊要求,可在 Count.vue
直接调用commit
提交,而不必等到 actions
提交。
getters和state的关系类似于computed和data
效果,标签中可以写成如下这样,使用 sum
而不用写 $store.state.sum
对象写法
数组写法
需要state中的名字和结构中的名字相同。
需要import引入。
和mapState相似,读取的是getters中的数据。
不同组件使用的配置分开写,开启命名空间。
引入
使用
mutations和actions
不借助map的写法。getters中数据的读取
不借助map的写法。actions和mutations。
安装:npm i vue-router@3
(vue2只能用3版本)
在main.js引入:
新建 src/router/index.js
,创建一个路由器
在main.js引入创建的路由器并添加相应的配置项
实现路由切换,router-link 渲染时会生成 a 标签。
指定组件呈现位置
整体:
路由组件和一般组件分别放在src/pages
和src/components
文件夹中。
案例:
配置子路由,需要注意的是子路由的 path 不用写 /
。
引用:to 里面路径要写两级
字符串写法:
在 router-link 标签的 to 属性中传参,给子路由组件。参数存在 $route.query
中。
在子路由组件中使用参数
路由配置中使用如下方式占位,声明接收参数。
对象写法
只能用 name ,不能用 path 。
子路由组件接收参数
路径过长时可简化路由跳转。
配合传参
而使用回调函数实现,例如 @click="pushShow"
。
router-link 标签会生成一个 a 标签,但是有时需要使用其他标签,如 button。
分别控制页面的后退和前进。
go可以一次前进多步或后退多步,如下是连续前进3步,参数为负数则后退。
为何需要缓存,有时在 input 中进行了输入,到别的组件再回来希望输入还在。
使用 keep-alive
将展示区包裹起来
include="News"
表示只缓存名称为 News
的路由组件,News为组件名而不是路由名。不写 include
则在该展示区的组件都将缓存。
写在 index.js 里面。
前置路由守卫。
简化写法,在路由配置项增加自定义属性。
需使用meta
配置项添加自定义属性。
后置路由守卫
可以修改一些信息,例如网页标题
写在路由配置里面。
独享路由守卫只有前置守卫没有后置守卫。
有两个时间点,都需要调用next放行,beforeRouteLeave 和 后置守卫不同,是在离开时调用。
通过路由规则进入才会调用,直接使用组件标签不会调用。
饿了么的。
官网:https://element.eleme.cn
在终端安装:npm i element-ui
最好引入时使用按需引入,减小代码体积。