vue基础

VUE是目前前端最火的两个框架之一
是通过修改数据自动改变dom数据的框架,几乎完全的省去了dom的操作,目前vue的版本是2.x

vue有两种使用方式,一种是直接引入js,一种是使用vue-cli,也就是脚手架

不管是使用哪种,写法都是没变的,只是脚手架用在更加大型的项目,脚手架后面再说

内容全部来自vue官网
这是我第一次认真的看vue的开发文档,以前都是看视频学习的,这才发现vue还有这么多看都没看过的API

需要学会的全部内容

  • 生命周期
  • 指令【太多了,不写了】
  • 选项/dom【ref】
  • 选项/数据【data,props,computed,methods,watch,$refs$nextTick
  • 全局API的【use,set,directive,component,filter】
  • 外部的【$router$store,axios】

引入

这里是一些基础的使用,所以就直接引入js做栗子

<div id="app">
  {{ message }}
</div>
// 外部CDN
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
<script type="text/javascript">
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

生命周期 和 ref
生命周期在大型的插件封装里是非常常见的,是表示当前运行阶段
vue的声明周期很多个,用到的有

  1. created:表示data数据已经加载,计算属性,watch,methods都执行好了,但是el还没挂载,第一次加载执行时用这个生命函数,我们去看vue的标签,写的时候可能是<vue></vue>但在页面上调试其实是个div,就是el被解析后挂载后的效果
  2. mounted:当前el已经挂载得差不多了,如果需要等el完全挂载,可以配合$nextTick使用,这个阶段是用来调用ajax
  3. updated:当数据发生变化,就会执行这个

生命周期函数不能使用箭头函数

<div id="app">
   <div ref="tt"> {{ message }} </div>
</div>
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  },
  created(){
	 // 此时没有el
         console.log(this.$refs)  //underfined
  },
  mounted(){
      this.$nextTick(function(){
	  // 这里是执行ajax的  
          console.log(this.$refs)  //{tt:div}
      })
  },
  updated(){
      this.$nextTick(function(){
	 // 数据变化执行这个
      })
  }
})

指令

<div id="app">
<!-- 数据显示的指令
     跟v-text一样但是用字符串模板{{}} 更好,还能执行方法
     v-html 是很少用的,一般用在后台返回富文本数据时使用  -->
    <div v-text="msg"></div>
    <div v-html="html">会识别html标签</div>
    <div>{{ msg + "aa" }} 可以写其他文字</div>

<!-- 逻辑判断的指令
     v-if是直接看不到dom,v-show是display:none -->
    <div v-show="show">显示</div>
    <div v-show="!show">隐藏</div>
    <div v-if="str === 'A'">A</div>
    <div v-else-if="str === 'B'">B</div>
    <div v-else>Not A/B</div>

<!-- 循环断的指令,可以循环数组,对象,字符串,数字 
     v-for要配合 :key 使用 
     v-for 不要跟 v-if 放在一起 -->
     <div v-for="value,key,index in obj" :key="key">{{key}}:{{value}}--{{index}}</div>
     <div v-for="value,index in arr" :key="value">{{value}}--{{index}}</div>

<!-- 事件绑定的指令,简写为【@】,配合methods使用,
     不传参是不写括号的
     事件修饰符:stop 阻止冒泡,
                prevent 阻止默认事件,
                self 只能亲自执行不被冒泡执行,相当于event.target,
                once 只执行一次
                native 使用在自定义组件上,查看《vue的自定义》笔记 -->
     <input type="text" v-on:blur="myBlur($event)" />
     <button @click="myClick">点击</button>

<!-- 变量绑定的指令,简写为【:】
     最常用的地方是 key,组件传参,src,href,type等-->
     <input v-bind:type="type" />
     <a :href="href"> 可以通过 data里改href 修改 a的href </a>

<!-- 表单双向绑定的指令  -->
     <input type="text" v-model="text">	<span>{{text}}</span> <br>
     <input type="password" v-model="password">	<span>{{password}}</span> <br>
     <input type="radio" v-model="radio" value="radio1"><input type="radio" v-model="radio" value="radio2">  <span>{{radio}}</span> <br>
     <input type="checkbox" v-model="checkbox" value="checkbox1"><input type="checkbox" v-model="checkbox" value="checkbox2">  <span>{{checkbox}}</span> <br>
     <select v-model="select">
        <option value="select1">select1</option>
        <option value="select2">select2</option>
        <option value="select3">select3</option>
     </select> <br>
</div>
var app = new Vue({
  el: '#app',
  data: {
    msg: 'Hello Vue!',
    html:"<input type='text'>",
    show: true,
    str: 'A',
    obj:{
	"name":"pdt",
	age:18
    },
    arr:[10,20,30,40],
    type:"password",
    href: "http:www.baidu.com",
    text: "text",
    password:"pass",
    radio:"radio2",
    checkbox:["checkbox1","checkbox2"],
    select:"select2",
  },
  methods:{
    myBlur(e){ console.log(e.srcElement.value) },
    myClick(){ ... }
  },
})

特殊的key指令
key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes,如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素,有相同父元素的子元素必须有独特的 key,重复的 key 会造成渲染错误

还有一个问题就是vue格式的dom标签在生命周期没进行到mounted之前是显示的,会让页面非常的难看
所以应该先隐藏,vue有个无用的指令叫v-cloak,把这个标签写在最高级dom上,给这个属性添加隐藏功能,等到vue把el挂载这个属性就会失效,页面也正好展示出来

[v-cloak] {
  display: none;
}
<div id="app" v-cloak > ... </div>

选项/dom
就是给dom元素上加上ref="xxx"的值,相当于id,然后可以通过 this.$refs获得一个对象,这个对象里装着所有带有 ref 属性的dom元素,这个是很少使用,只有部分插件有要求使用这个属性

选项/数据
上面的指令是数据和dom的绑定和显示,这个是vue插件替我们完成的,我们就不用再去写xx.value=="xx",xx.innerHTML="xx"了,所以只需要自己修改数据就行

我们一般使用的vue的数据写在4个地方

  1. data对象里
  2. 计算属性computed里
  3. prop对象里(由父组件的v-bind传过来的,这个后面单独讲)
  4. 还有vuex (这个后面单独讲)
<div id="app">
    <div> {{ msg }} </div>
    <div> {{ msg2 }} </div>
    <div v-show="show">显示</div>
    <div v-show="!show">隐藏</div>
    <button @click="A">显示/隐藏</button>
    <button @click="B">点击修改msg的值</button>	
</div>
var app = new Vue({
  el: '#app',
  data: {
    msg: 0,
    show: true,
  },
  methods:{
    // 修改data的数据只能用this.【data里的key】 = 【新value】
    A(){ this.show = !show; // 取反 }

    // 修改data的数据只能用this.【data里的key】 = 【新value】
    B(){ this.msg = new Date().getTime(); }
  },
  computed:{
     // 在计算属性里的值不需要写在data里,重复会冲突
     // 一旦计算属性里的相关值发生变化,这个值就会重新计算
     // 计算属性是需要return才能给自己赋值
     msg2(){
	return new Date(this.msg).getFullYear()+"-"+ (new Date(this.msg).getMonth()+1) + "-"+ new Date(this.msg).getDate() + " "+ new Date(this.msg).getHours() + ":"+ new Date(this.msg).getMinutes() + ":"+ new Date(this.msg).getSeconds()   
     } 
  } 
})

vue的watch监听
这个是计算量很大的方法,vue建议能用computed尽量不用watch,但是我经常用它监听vuex的初始化数据,他是监听上面的四个数据对象的某个数据,需要四个数据对象里先有需要监听的值
注意: watch和computed不要去操作相同的数据,不然相互计算会陷入死循环

data:{
   name:"xxx"
},
watch:{
   name(){
      console.log("值发生了改变")
   }
}

watch的immediatedeep

watch: {
  // 不能写成函数了
  firstName: {
    handler(newName, oldName) {
      this.fullName = newName + ' ' + this.lastName;
    },
    // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
    immediate: true, //默认是false

    // 当watch监听的是对象,对象里的值改变是不被监听的,需要加上深度监听
    deep: true   //默认是false
  }
}

methods是存方法的地方,$refs在上面提到了

还有最后一个this.$nextTick这个是配合vue的数据更新使用的,vue的数据更新后的dom更新并不是实时的,他不是你把a从1变成2他就去改一次的,他是用类似防抖的方式去控制数据变化的,他会把数据的变化攒着一口气再更新一次dom,而this.$nextTick回调的就是下一次dom更新完要执行的东西
这个方法用得也不多,在使用轮播图插件的时候,一开始轮播图是空的,所以不会动,等图片数据从ajax请求下来后,数据更新上去但是轮播图还是不会动,就需要执行轮播图滚动的方法,如果同步执行,10次可能有5次不生效,因为你执行滚动方法的时候dom还没更新,所以解决方案有弄个定时器等大概1-2s后执行滚动方法,或者把滚动方法写在this.$nextTick的回调里

数据添加的规定
需要用到的数据有两种,一种是一开始就声明好了的,比如现在data里先声明了name属性,那这个属性在vue的creat阶段就被监听了,但是如果是后期添加的数据,是不被监听的

<div id="app">
    <div v-for="value in opt.arr" :key="value">{{value}}</div>
    <div v-for="value,key in opt.obj" :key="value">{{key}}--{{value}}</div>
    <button @click="A">添加数组</button>
    <button @click="B">添加对象</button>	
</div>
var app = new Vue({
  el: '#app',
  data: {
     opt:{},
  },
  methods:{
    A(){ 
      this.opt.arr=[{name:"arr"}];
      console.log(this.opt.arr)
    },
    B(){ 
      this.opt.obj={name:"obj"};
      console.log(this.opt.obj)
    }
  } 
})

会发现虽然打印有数据,但是页面没数据,因为vue不知道有这个数据,js知道
想要让vue知道,需要用vue规定的添加方式

  methods:{
    A(){
      // 在this是代表vue实例的地方这么写 
      this.$set(this.opt,"arr",[{name:"arr"}])

      // 在this不是vue的实例的地方,比如插件的上下文里
      // Vue.set(this.opt,"arr",[{name:"arr"}])  
      console.log(this.opt.arr)
    },
    B(){ 
      // 在this是代表vue实例的地方这么写 
      this.$set(this.opt,"obj",{name:"arr"})

      // 在this不是vue的实例的地方,比如插件的上下文里
      // Vue.set(this.opt,"obj",{name:"arr"})
      console.log(this.opt.obj)
    }
 } 

数据更新的规定

当更新一个普通的数据时,直接xx="xx",vue就能反应过来,但是如果是更新数组或者对象,就有些规定了,不然就会出现数据我改了,但是没效果的BUG,具体查看vue官网的文档

vue规定修改数组用下面的方法
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
如果是
filter()、concat() 和 slice() 。它们不会改变原始数组,而总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组:

example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)
})
vm.items[1] = 'x' // 不是响应性的
// 可以改用
Vue.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)

vm.items.length = 2 // 不是响应性的
// 可以改用
vm.items.splice(newLength)

// 清空数组
this.arr = []

vue规定修改对象用下面的方法
对象的数据需要改没有数组那么多的规定就直接赋值就行,新来的数据用set添加
如果需要融合对象

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

可以看出,封装是有封装的局限性的,他有很多的限制,这也是为什么学习原生比学习框架更好的原因

剩下的知识点有
全局API的【use,directive,component】
外部的【$route$store,axios】

剩下的这些都是在脚手架上用的多,用js引入的小项目小页面很少用

use是用于引入插件的
directive是自定义指令
component是自定义组件
filter是自定义过滤器
$route是vue-router的路由数据
$store是vuex的数据
axios是新的请求方式,因为省去了操作dom,就不会再引入jq了,不用jq了,jq的ajax也就不用了
除了$store其他的几个在引入型的vue使用中都可以用的,需要用到就自行百度,查看官方文档也有,下一篇《vue-cli》

posted @ 2019-12-15 22:31  一个年轻淫  阅读(213)  评论(0编辑  收藏  举报