vue开发笔记

105 阅读5分钟

1.vue简介

vue是一个渐进式的前端框架,渐进式意味着你可以将vue作为你应用的一部分嵌入其中,或者如果你希望将更多的业务逻辑使用vue实现,那么vue的核心库以及其生态系统。比如Core+vue-router+VUex+axios,也可以满足你各种各样的需求。

vue的特点和web开发中常用的高级功能:

  1. 解耦视图和数据
  2. 双向数据绑定
  3. 可复用的组件
  4. 前端路由技术
  5. 状态管理
  6. 虚拟DOM

2.VUE的安装使用

方式一:直接CND引入

<!-- 开发环境版本,包含了有帮助的命令行警告 --> 
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

方式二: 下载和引入

// 开发环境 https://vuejs.org/js/vue.js
// 生产环境 https://vuejs.org/js/vue.min.js

方式三:NPM安装

3.VUE体验

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
    <div id="app">
        {{ str1 }}
    </div>
</body>
<script>
    
    var vm = new Vue({    //这个Vue对象用来控制某一个标签里面的数据
        el:"#app",   //要控制的标签
        data:{
            str1:"hello vue",   //定义一个数据,在id为app的标签内部去使用
        }
    })
</script>
</html>

4.VUE常见语法格式

4.1 模板语法

<div id="app">
        <p>{{ str1 }}</p>
        <p>{{ str1.split("").reverse().join("") }}</p>
        <p>{{num+1}}</p>
        <p>num1和numn2的最大值是:{{ num1>num2 ? num1 : num2 }}</p>
    </div>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                str1:"hello",
                num:20,
                num1:40,
                num2:80
            }
        })
   </script>

4.2 v-bind控制标签属性

<div id="app">
        <a v-bind:href="bd">百度</a>
        <a :href="tb">淘宝</a>
        <a :href="tb">淘宝</a>
    </div>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                bd:"https://www.baidu.com",
                tb:"https://www.taobao.com"
            }
        })
    </script>

4.3、v-on事件格式

<div id="app">
        <p>{{num}}</p>
        <button v-on:click="num+=1">点我数字增加</button>
        <button v-on:click="add">点我数字加5</button>
        <button @click="add2(10)">点我数字加10</button>
    </div>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                num: 20
            },
            methods:{
                add:function(){
                    this.num += 5
                },
                add2(){
                    this.num += 10
                }
            }
        })
    </script>

5. VUE中的MVVM

  1. view层 视图层,在前端里就是我们常说的DOM层,主要作用是给用户展示各种信息;

  2. Model层 数据层,数据可能是我们自定定义的数据,或者是从网络请求下来的数据;

3.ViewModel层:

视图模型层,是View层和Model层沟通的桥梁;一方面它实现了数据绑定(Data Binding),将Model的改变实时反应到View中;另一方面它实现了DOM监听,当DOM发生改变可以对应改变数据(Data)

6.reduce方法的使用

利用reduce方法遍历数组的每一个元素,reduce()调用结果最后返回一个最终值(最后一次return值)。

var arr = [
       {name: 'Vuejs入门', price: 99, count: 3},
       {name: 'Vuejs底层', price: 89, count: 1},
       {name: 'Vuejs从入门到放弃', price: 19, count: 5},
    ]

    //数组名.reduce(回调函数,pre的初始值)
    arr.reduce(function(pre, current){
        // reduce这个方法被调用时,会遍历arr这个数组的每一个元素,每遍历一个元素,就执行一次这里的代码
        // current表示当前正在遍历的这个元素
        // pre 是上一次的这个函数return的值
        // !!!因为第一次遍历没有上一个return值,所以,交给了第二个参数,设置pre的初始值
        console.log(pre, current)
        return 10
    },0)

	//!!!并且reduce方法最终会返回最后一次的return值

7.自定义指令

// 注册一个全局自定义指令 v-demo
Vue.directive('demo', {
	inserted: function (el, binding) {
		
		console.log(el, binding);
	},
    update(el, binding){}
})

局部自定义指令格式:

// 组件中注册局部指令
new Vue({
	el: '#app',
	data: {},
	directives: {
		demo: {
			inserted: function (el, binding) {
				cosnole.log(el, binding);
			}
		}
	}
})

自定义指令的使用:

// 在模板中使用自定义指令
<div v-demo>
    
</div>

函数:

  • inserted :被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。

参数:

  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象,包含以下属性:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-demo="1 + 1" 中,绑定值为 2
    • oldValue:指令绑定的前一个值
    • expression:字符串形式的指令表达式。例如 v--demo="1 + 1" 中,表达式为 "1 + 1"
    • modifiers:一个包含修饰符的对象。例如:v-demo.foo.bar 中,修饰符对象为 { foo: true, bar: true }

实现类似v-show的自定义指令

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <p v-demo="status">12</p>
    <button @click="status = !status">取反</button>
  </div>
</body>
<script>
const vm = new Vue({
  el: '#app',
  data: {
    status: true
  },
  directives: {
    demo: {
      inserted(el, binding) {
        console.log(el, binding)
        if (binding.value) {
          el.style.display = 'block'
        } else {
          el.style.display = 'none'
        }
      },
      update(el, binding){
        console.log(el, binding)
        if (binding.value) {
          el.style.display = 'block'
        } else {
          el.style.display = 'none'
        }
      }
    }
  }
})
</script>
</html>

8.双向数据绑定原理

Vue 最独特的特性之一,是其非侵入性的响应式系统。数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新。Vue里面是怎么做到的的呢?其实就是使用了Object.defineProperty 把Vue内的属性全部转成 getter/setterObject.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

Object.defineProperty 实现了对象劫持这个功能

github.com/vuejs/vue/b…

github.com/vuejs/vue/b…

vue双向数据绑定原理:

借助Object.defineProperty()对数据进行劫持,并结合发布-订阅者模式,来实现双向数据绑定

语法:

Object.defineProperty(obj, prop, desc)

  1. obj 需要定义属性的当前对象
  2. prop 当前需要定义的属性名
  3. desc 属性描述符

数据属性:

通过Object.defineProperty()为对象定义属性,有两种形式,分别为数据描述符,存取描述符,下面分别描述两者的区别:

  1. value 表示它的默认值
  2. writable 如果为true标识可以被修改,如果为false标识不能被修改(默认值为false)
  3. configurable 描述属性是否配置,以及可否删除,可以认为是总开关 默认值 false(不可删除)
  4. enumerable 描述属性是否出现在for in 或者 Object.keys()的遍历中 默认值false(不能遍历)
let obj = {};
Object.defineProperty(obj, 'name', {
    value: '张三'
})
obj.name = '李四'
console.log(obj.name) // 张三

let obj = {};
Object.defineProperty(obj, 'name', {
    value: '张三',
    writable: true
})
obj.name = '李四'
console.log(obj.name)
let obj = {};
  Object.defineProperty(obj, 'name', {
    value: '张三',
    writable: true,
    configurable: true,
    enumerable: true
  })
  obj.name = '李四'
  // delete obj.name
  console.log(obj.name) // 李四
  console.log(Object.keys(obj)) // ['name']

存取属性:

let obj = {};
let temp = null;
Object.defineProperty(obj, 'name', {
    get() {
        return temp
    },
    set(val) {
        temp = val
    }
})
obj.name = '李四'
console.log(obj.name)

面试题回答:

vue的双向数据绑定原理是什么?

vue数据双向绑定是通过数据劫持结合“发布者-订阅者模式”的方式来实现的。 vue是通过Object.defineProperty()来实现数据劫持,其中会有getter()和setter方法;当读取属性值时,就会触发getter()方法,在view中如果数据发生了变化,就会通过Object.defineProperty()对属性设置一个setter函数,当数据改变了就会来触发这个函数;

参考:segmentfault.com/a/119000001…

参考:zhuanlan.zhihu.com/p/51357583

9.过滤器的使用

Vue的过滤器用来对数据展示之前做一定的处理

	<div id="app">
       <!-- {{ 变量名 | 过滤器名 }} -->
        <p>{{ num | formatNum }}</p>
    </div>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                num:10
            },
            filters:{
                formatNum(val){   // 这个形参接收 | 符号前面的变量数据
                    return val + 50  //return后面的值就是将来展示在页面上的值(即过滤之后的值)
                }
            }
        })
    </script>

过滤一个时间戳:

	<div id="app">
       <!-- {{ 变量名 | 过滤器名 }} -->
        <p>{{ timestamp | formatDate }}</p>
    </div>
    <script>
        // var timestamp = new Date().getTime()  // 获取时间戳
        // console.log("日期是:",timestamp)
        var vm = new Vue({
            el:"#app",
            data:{
                timestamp:new Date().getTime()
            },
            filters:{
                formatDate(val){   // 这个形参接收 | 符号前面的变量数据

                    var now = new Date(val)
                    var year=now.getFullYear(); 
                    var month=now.getMonth()+1; 
                    var date=now.getDate(); 
                    var hour=now.getHours(); 
                    var minute=now.getMinutes(); 
                    var second=now.getSeconds(); 
                    return year+"-"+month+"-"+date+" "+hour+":"+minute+":"+second; 

                }
            }
        })
    </script>

9.2、全局过滤器

多个app共用的过滤器可以作为全局过滤器来书写

	<div id="app">
       <!-- {{ 变量名 | 过滤器名 }} -->
        <p>{{ timestamp | formatDate }}</p>
    </div>
    <div id="app2">
        <!-- {{ 变量名 | 过滤器名 }} -->
        <p>第二个: {{ timestamp | formatDate }}</p>
    </div>
    <script>

        //全局过滤器
        // Vue.filter("过滤器名字",(val)=>{})
        Vue.filter("formatDate",(val)=>{
            var now = new Date(val)
            var year=now.getFullYear(); 
            var month=now.getMonth()+1; 
            var date=now.getDate(); 
            var hour=now.getHours(); 
            var minute=now.getMinutes(); 
            var second=now.getSeconds(); 
            return year+"-"+month+"-"+date+" "+hour+":"+minute+":"+second; 
        })

        var vm2 = new Vue({
            el:"#app2",
            data:{
                timestamp:new Date().getTime()
            }
        })
        // var timestamp = new Date().getTime()  // 获取时间戳
        // console.log("日期是:",timestamp)
        var vm = new Vue({
            el:"#app",
            data:{
                timestamp:new Date().getTime()
            },
            // filters:{
            //     formatDate(val){   // 这个形参接收 | 符号前面的变量数据

            //         var now = new Date(val)
            //         var year=now.getFullYear(); 
            //         var month=now.getMonth()+1; 
            //         var date=now.getDate(); 
            //         var hour=now.getHours(); 
            //         var minute=now.getMinutes(); 
            //         var second=now.getSeconds(); 
            //         return year+"-"+month+"-"+date+" "+hour+":"+minute+":"+second; 

            //     }
            // }
        })
    </script>