> ### 1.简介:
>
> Vue是一套用于构建用户界面的**渐进式框架**。与其他大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅容易上手,还便于与第三方库或既有项目整合。另一方面,当与***现代化的工具链***以及各种支持类库结合使用时,Vue也完全能够为复杂的单页应用提供驱动。用来做单页面应用--index.html,页面跳转用的vue插件路由来实现跳转。
>
> vue特点
>
> 1.前端三大主流框架之一 vue react Angular
>
> 2.轻量级框架 体积更小
>
> 3.生态圈广泛,适合初学者
>
> 4.基于mvvm模式,可以实现双向数据绑定
【vue】https://cn.vuejs.org/
【gitee封面人物:尤雨溪谈Vue.js】https://gitee.com/gitee-stars/14
【采访 Vue 作者尤雨溪】https://www.jianshu.com/p/3092b382ee80
【Object.defineProperty()详解 拓展理解vue源码】https://www.cnblogs.com/ldq678/p/13854113.html https://zhuanlan.zhihu.com/p/22695144
```javascript
1-Vue基本渲染-插值
### js代码
window.onload = function () {
// 创建vue实例,vue实例要与模板(DOM)绑定
let vm= new Vue({
el: "#app",
data: {// 数据模型
msg:'hello world'
},
// 函数
methods: {
changeData(){
if(this.msg==='hello world'){
// 更改数据模型中的数据
// 获取数据模型中的数据
// 在vue实例内访问vue实例身上的属性和方法
this.msg='你好我是修改后的值'
}else{
this.msg='hello world';
}
}
},
})
}
### html代码
<!-- 以前把msg作为元素文本的,获取dom节点,绑定事件,dom.innerText=msg-->
<div id="app">
<!-- 在模板内访问vue实例中数据模型中的数据 插值 -->
<!-- 基本渲染 插值 -->
{{msg}}
<p>{{msg}}</p>
<!-- 点击按钮 改变数据模型中的数据msg变量 -->
<button @click='changeData'>点我修改数据模型msg数据</button>
</div>
数据模型更改,引发了vm驱动
```
> ### 2.MVVM
>
> Model 数据模型
>
> View 视图
>
> VM ViewModel 连接视图和数据模型的纽带,数据模型发生了变化,vm通知视图修改;视图发生了变化,vm通知数据模型进行相对应的修改.
>
> 视图模型 帮我们把数据模型中的数据渲染到视图中 相当于一个纽带
>
> ![image-20220328125343303](../../../图片/image-20220328125343303.png)
>
> 优化渲染:当前数据模型发生改变只改变对应的视图,只渲染对应的视图层
>
> mvvm介绍:
> m指model服务器上的业务逻辑操作,v指view视图(页面),vm指ViewModel模型跟视图间的核心枢纽,比如vue.js。![image-20220328125353513](../../../图片/image-20220328125353513.png)
>
> 可以将上图中的``` DOM Listeners ```和 ``` Data Bindings ```看作两个工具,它们是实现双向绑定的关键。
>
> 从View侧看,ViewModel中的``` DOM Listeners ```工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据;
>
> 从Model侧看,当我们更新Model中的数据时,``` Data Bindings ```工具会帮我们更新页面中的DOM元素。
```javascript
### 2.数据模型
let vm=new Vue({
el:'#app',
data:{
color:'white',
age:12,
time:new Date()
},
methods:{
sayName(){
console.log(this.name)
},
}
})
// 每隔一秒重新查询一次时间
setInterval(()=>{
vm.time=new Date()
},1000)
// 查看vue实例对象
console.log(vm)
console.log(vm.color)
vm.age=15
console.log(vm.age)
```
> ### ****** **** 3.生命周期(钩子函数)
>
> 从vue**实例创建**到**虚拟dom产生**再到**数据绑定**监听**数据渲染**以及**销毁**的整个过程
>
> ![life](../../../图片/life.png)
```javascript
生命周期的第一步首先是创建vue实例,并且进行初始化。
### vue实例初始化阶段
beforeCreate
在初始化的时候调用了beforeCreate,完成了vue实例的生命周期相关属性的初始化以及事件的初始化。这个时候还不能访问数据模型中的data和methods中的方法。
created
在初始化完毕之后,完成vue的数据注入以及数据监听操作,该构造的执行意味着vue实例创建完毕,可以进行data数据模型和和methods方法的访问
### vue实例挂载阶段
beforeMount
在created之后,vue会判断实例中是否含有el属性,如果没有vm.$mount(el),接着会判断是否含有template属性,如果有将其解析为一个render function,如果没有将el指定的外部html进行解析。这里只完成了模板的解析但是数据并没有绑定到模板中。
mounted
创建vm.$el替换el,实际上完成的是数据绑定操作,在其间执行了render函数,将模板进行了解析,将数据进行了动态绑定
### vue实例更新阶段
beforeUpdate
更新虚拟dom节点
updated
完成了页面的重新渲染
### vue实例销毁阶段
beforeDestroy
销毁之前调用,此时可以访问vue实例
destroyed
完成了监听器,子组件,事件监听等移除,销毁vue实例对象。
```
```javascript
### js代码
<script>
let vm=new Vue({
el:"#app",
data:{
msg:'hello world'
},
beforeCreate(){
console.log('vue实例初始化之前')
},
created() {
console.log('vue实例初始化好了,可以访问到数据模型中的数据以及methods方法')
},
beforeMount() {
console.log('实例挂载之前')
},
mounted(){
console.log('实例挂载完毕,可以获取dom节点,一般不操作dom')
},
beforeUpdate() {
console.log('实例发生改变之前触发该生命周期')
},
updated() {
console.log('实例发生改变后页面视图发生变化,触发该生命周期')
},
beforeDestroy() {
// console.log('实例销毁之前,仍然可以访问到数据模型中的数据和方法')
},
destroyed() {
// console.log('实例销毁完毕,销毁了监听器和事件监听以及子组件');
},
methods:{
sayHello(){
console.log(this.msg)
},
}
});
console.log(vm)
setTimeout(()=>{
// vm.msg='unhello';
vm.$destroy()
},3000)
</script>
### html代码
<div id="app">
{{msg}}
</div>
```
> ### 4.模板语法
>
> **介绍:**
>
> **vue使用了基于HTML的模板语法,允许开发者声明式地将DOM绑定至底层Vue实例的数据。所有 Vue的模板都是合法的 HTML,所以能被遵循规范的浏览器和HTML解析器解析。在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接编写渲染函数及render,使用可选的 JSX 语法(react采用的就是jsx语法)。**
>
> ##### 1.插值: 1.基本渲染 {{}}
>
> **当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。**
>
> `渲染最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值。`
>
> ##### 2.原始html(v-html,解析标签中的文本内容)
>
> ##### 3.属性v-bind(可以使用:简写 表示绑定的是一个变量)
>
> ##### 4.事件v-on:click (可以使用@简写)
>
> ##### 5.javascript表达式(可以进行js逻辑运算)
```javascript
```Mustache 标签```将会被替代为对应数据对象上 ```msg property```的值。无论何时,绑定的数据对象上 ``` msg property ``` 发生了改变,插值处的内容都会更新。当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时就已经存在于 `data` 中的 property 才是**响应式**的。也就是说如果你添加一个新的 property,比如: vm.hobbies='跳舞上树翻跟斗'。那么对 `hobbies` 的改动将不会触发任何视图的更新。如果你知道你会在晚些时候需要一个 property,但是一开始它为空或不存在,那么你仅需要设置一些初始值。
打开页面2s后页面显示的内容由 ``` 'hello world' ``` 变化为 ``` 'hello vue' ``` :
1.文本渲染
### js代码
let vm=new Vue({
el:'#app',
data:{
msg:'hello world',
animal:['大笨象','小猴子','狐狸']
},
methods:{
}
});
setTimeout(()=>{
// vm.msg='hello vue' //不与响应式属性一起更新,stat的改变将不会触发任何视图更新
vm.hobbies='跳舞上树翻跟斗'
},2000)
### html代码
<div id="app">
<div>{{animal}}</div>
<div>{{hobbies}}</div>
<div>{{msg}}</div>
</div>
也可以使用v-once指令,执行一次性地插值,当数据发生改变,插值出的内容不会更新
### js代码
let vm=new Vue({
el:'#app',
data:{
msg:'hello world'
}
})
setTimeout(()=>{
vm.msg='hello vue'
},2000)
### html代码
<div id="app" >
<!-- {{ msg }} 不会再更改,一直是hello world -->
<div v-once>{{msg}}</div>
</div>
```
```javascript
2.如果我们向后台请求的数据是一段HTML代码,如果我们直接通过{{}}来输出,会将HTML代码也一起输出。双大括号会将数据解析为普通文本,而非 HTML 代码。但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。如果我们希望解析出HTML展示
可以使用**v-html**指令:该指令后面往往会跟上一个string类型,会将string的html解析出来并且进行渲染。
<div id="app">
<div v-html='url'></div>
</div>
new Vue({
el:'#app',
data(){
return {
list:"All the changan flowers in one day",
url:'<a href="https://www.baidu.com">百度一下</a>'
}
}
})
```
```javascript
3.属性渲染
双大括号语法不能作用在元素属性上,遇到这种情况应该使用**v-bind**指令 :
### js代码
new Vue({
el:"#app",
data(){
return {
msg:'我是数据模型中的msg',
title:'我是鼠标悬浮就会展示的title'
}
}
})
### html代码
<div id="app">
<!-- <div v-bind:title='title'>{{msg}}</div> -->
<!-- 简写为:属性名="变量名" -->
<div :title='title'>{{msg}}</div>
</div>
```
```javascript
4.事件渲染
可以使用v-on给当前元素绑定事件,也可以使用简写形式@click
###js代码
new Vue({
el:'#app',
data:{
},
methods:{
test(){
alert(1)
}
}
})
### html代码
<div id="app">
<button v-on:click='test'>点我点我</button>
<button @click='test'>点我点我</button>
</div>
```
```javascript
5.javaScript表达式
###js代码
new Vue({
el:'#app',
data(){
return {
animal:['大笨象','小猴子','狐狸'],
count:1001,
firstname:'ren',
lastname:'terry'
}
}
})
###html代码
<div id="app">
<ul>
<li v-for='(item,index) in animal'>
{{index+1}}-{{item}}-{{index}}
</li>
</ul>
<div>{{Number(animal)}}</div>
<div>{{Boolean(animal)}}</div>
<div>{{count*100}}</div>
<div>{{firstname}}--{{lastname}}</div>
</div>
```
> ### 条件渲染
>
> 1.**v-if(可以单独使用)**,**表达式为true的时候渲染使用v-if属性的元素,否则使用v-else渲染**
>
> 2.**v-show(切换css样式中display属性),频繁切换css样式,使用v-show****
>
> 不推荐同时使用 v-if 和 v-for。当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
>
> ****** `v-show 与 v-if 的区别 :
> v-show 不支持 v-else
> v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
> v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
> v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做;直到条件第一次变为真时,才会开始渲染条件块。
> v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
> `
> v-if对应的是元素/标签的添加或者删除
> 满足条件添加元素
> 不满足条件删除元素
> v-show对应的是元素的CSS样式中的display属性
> 满足条件对应的是元素的显示 display:block
> 不满足条件对应的是元素的隐藏 display:none
> v-show用于频繁的切换css样式
```javascript
### javascript代码
new Vue({
el:"#app",
data:{
mine:false,
not:'啥也不是',
isShow:false
}
})
### html代码
<div id="app">
<div v-if='mine'>是我是我</div>
<div v-else>{{not}}</div>
<div v-show='isShow'>还得看我</div>
</div>
```
> ### 列表渲染 v-for
>
> 用于将列表数据进行渲染。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
>
> ### *** key
>
> Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做可以使 Vue 变得非常快。但是有些时候,我们却不希望vue复用,这时候Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key
```javascript
### html代码
<ul>
<li v-for='(item,index) in animal' :key='item'>
{{index+1}}-{{item}}-{{index}}
</li>
</ul>
### js代码
new Vue({
el:'#app',
data(){
return {
animal:['大笨象','小猴子','狐狸'],
}
}
})
```
> ### style绑定
>
> 操作元素的class列表和内联样式是数据绑定的一个常见需求,因为它们都是attribute,所以我们可以用v-bind处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将v-bind用于class和style时,Vue做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
```javascript
### html代码
<div :style="styleObj">Hello</div>
<div :style="{color:currentColor}">World</div>
<div :style="[styleObj2,styleObj]"> hello world</div>
### css代码
new Vue({
el: '#app',
data: {
currentColor: 'blue',
styleObj: {
color: 'red',
"font-size": '30px',
},
styleObj2: {
background: 'pink',
color: 'blue'
}
},
})
```
> ### class绑定
>
> 操作元素的class列表和内联样式是数据绑定的一个常见需求,因为它们都是attribute,所以我们可以用v-bind处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将v-bind用于class和style时,Vue做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
```javascript
### css样式
.red {
color: red;
}
.size {
font-size: 30px;
}
### html代码
<div id="app">
<div class="red" :class="{size:true}">Hello</div>
<div :class="{red:false,size:true}">World</div>
<div :class="[{red:true},{size:false}]">hello World</div>
</div>
### js代码
new Vue({
el: '#app',
data: {
},
})
```
********* 【面试题:为什么在大型项目中data是一个函数而不是一个对象】
```javascript
组件是一个可复用的实例,当你引用一个组件的时候,组件里的data是一个普通的对象,所有用到这个组件的都引用的同一个data,就会造成数据污染。
不使用return包裹的数据会在项目的全局可见,会造成变量污染;
使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件。
当一个组件被定义, data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。
```
```javascript
//1、在简单的vue实例中看到的Vue实例中data属性,如下所示:
<script>
let vm=new Vue({
el:'',
data:{},//数据可以直接挂在vue实例上
methods:{}
})
</script>
//2、在使用组件化的项目中,如下所示:
//每一个.vue文件中都对应一个vue实例,该vue实例的构造函数参数由当前页面的export default提供
<script>
export default{
data(){
return {
}
},
methods:{}
}
}
</script>
```
> ### 排序
>
> 冒泡排序 Bubble Sort
>
> 1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
> 2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
> 3.针对所有的元素重复以上的步骤,除了最后一个。
> 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
```javascript
// 思路 前一项与后一项比较 前一项大于后一项交换位置
let arr=[5,2,3,4,1];
let bubbleSort=(arr)=>{
// 控制比较的轮数
for(i=0;i<arr.length-1;i++){
// 控制每轮的比较
for(j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
let temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp
}
}
}
return arr
}
console.log(bubbleSort(arr))
```
```javascript
### 选择排序
第一次从待排序的数组元素中选出最小的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法
选择排序算法思想:在冒泡排序上做了优化,减少了交换次数,
在首轮选择最小的数放在第一项,一轮之后第一项是有序的了,第二轮从第二项开始选择小的数放在第二项,以此类推,直到整个数组完全有序。
let arr=[54,484,746,1,316,84,6];
let selectSort=(arr)=>{
for(i=0;i<arr.length-1;i++){
let temp=i;
for(j=i+1;j<arr.length;j++){
if(arr[j]<arr[temp]){
let swap=arr[j];
arr[j]=arr[temp];
arr[temp]=swap;
}
}
}
return arr
}
console.log(selectSort(arr))
```
```javascript
插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。
插入排序的基本思想是:每步将一个待排序的记录,按其值的大小插入前面已经排序的数组中适当位置上,直到全部插入完为止。
let arr=[132,04,97,45,38,67,48,95]; 6 n n-1 n
let insertSort=(arr)=>{
for(i=0;i<arr.length-1;i++){ // n-1个数已经排好序
for(j=i+1;j>0;j--){ // n个数要插入到前面的有序数列中
if(arr[j]<arr[j-1]){
let temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp
}
}
}
return arr
}
console.log(insertSort(arr))
```