vue基础-2

计算属性

(1) 基础例子

有的时候我们需要在模板中使用数据a,这个时候就需要用到表达式,但是有的地方我们需要对a数据进行一些简单的处理后才能使用,那么我们就会在表达式中写一些js逻辑运算

<div id="example">
 {{ message.split('').reverse().join('') }}
</div>

这样我们的维护就会非常困难,也不便于阅读

(2) 计算缓存 vs methods

我们就可以在methods里设置一个方法,在模板的表达式中使用这个方法

// 在组件中
methods: {
    reversedMessage: function () {
        return this.message.split('').reverse().join('')
    }
}

但是这个时候,只要vm中有数据变化,这个变化的数据可能和我们关注的数据无关,但是vm都会重新渲染模板,这个时候表达式中的方法就会重新执行,大大的影响性能

(3) data vs computed vs watch

这个时候其实我们可以使用监听器里完成:

在vm实例中设置watch属性,在里面通过键值对来设置一些监听,键名为数据名,值可以是一个函数,这个函数在数据改变之后才会执行,两个参数分别是更改前的值和更改后的值

 watch:{
        a: function (val, oldVal) {
            console.log('new: %s, old: %s', val, oldVal)
        }
    }

值还可以是一个方法名字,当数据改变的时候这个方法会执行

当数据为object的时候,object的键值对改变不会被监听到(数组的push等方法可以),这个时候需要设置深度监听:

c: {
        deep:true,
        handler:function (val, oldVal) {
            console.log('new: %s, old: %s', val, oldVal)
        }
    },

监听的handler函数前面的这几种写法都是在数据变化的时候才会执行,初始化的时候不会执行,但是如果设置immediate为true就可以了

watch:{
        num(newValue,oldValue){ //这样去写的话不会主动执行一次,需要更改依赖项的时候,才会执行!
        },
        num:{
            immediate:true, //初始化的时候主动执行一次handler
            handler:function(newValue,oldValue){
                this.nums = newValue*2
            }
        }
    }

我们在回到上面的问题,用监听器加上immediate属性就可以做到该效果,但是大家可以看到的是逻辑稍稍有点复杂

我们一般都会用到一个叫计算属性的东西来解决:

计算属性就是在实例配置项中通过computed来为vm设置一个新的数据,而这个新数据会拥有一个依赖(一条已经存在的数据),当依赖发生变化的时候,新数据也会发生变化

与方法的方式相比,它性能更高,计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

与watch相比,写起来简单,逻辑性更清晰,watch一般多用于,根据数据的变化而执行某些动作,而至于这些动作是在干什么其实无所谓,而计算属性更有针对性,根据数据变化而更改另一个数据

计算属性也拥有getter和setter,默认写的是getter,设置setter可以当此计算属性数据更改的时候去做其他的一些事情,相当于watch这个计算属性

 xm:{
        get:function(){//getter 当依赖改变后设置值的时候
            return this.xing+'丶'+this.ming
        },
        set:function(val){//setter 当自身改变后执行
            this.xing = val.split('丶')[0]
            this.ming = val.split('丶')[1]
        }
    }

Mixins

​ 混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。

​ 混入对象可以包含任意组件选项。

​ 当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

	<div id="app">
    	<button @click="a">a</button>
    	<p>{{b}}</p>
    </div>
  
    <script src="./base/vue.js"></script>
    <script>

      //在Vue里可以使用mixins来做代码的抽离复用,便于维护
      //一个mixin其实就是一个纯粹的对象,上面挂载着抽离出来的配置,
      //在某一个实例中,通过mixins选项导入后,此实例就拥有导入的mixin的配置
      //并且不会与原配置相互覆盖,而是合并到一起

      let common = {
        methods:{
          a(){
            console.log("a执行了")
          }
        },
        computed:{
          b(){
            return "b"
          }
        }
      }


      new Vue({
        el:"#app",
        mixins:[common]
      })
      
    </script>

数据请求

(1) vue-resource请求

从vue的2.0开始,作者说:vue-resource不再维护了

(2) fetch请求(规范)

why: XMLHttpRequest 是一个设计粗糙的 API,配置和调用方式非常混乱, 而且基于事件的异步模型写起来不友好。

查看兼容性: https://caniuse.com/#search=fetch

兼容性不好 polyfill: https://github.com/camsong/fetch-ie8

1 //get
2 fetch("**").then(res=>res.json()).then(res=>{console.log(res)})
3 fetch("**").then(res=>res.text()).then(res=>{console.log(res)})


4 //post
5 fetch("**",{
6 method:'post',
7 	headers: {
8 		"Content‐Type": "application/x‐www‐form‐urlencoded"
9 	},
10 	body: "name=zhangsan&age=100"
11 	}).then(res=>res.json()).then(res=>{console.log(res)});


12 fetch("/users",{
13 	method:'post',
14 	// credentials: 'include',
15 	headers: {
16 	"Content‐Type": "application/json"
17 },
18 	body: JSON.stringify({
19 		name:"zhangsan",
20 		age:100
21 	})
22 }).then(res=>res.json()).then(res=>{console.log(res)});

** Fetch 请求默认是不带 cookie 的,需要设置 fetch(url, {credentials: ‘include’})*

(3) axios请求

// get
axios.get("json/test.json?name=zhangsan&age=10").then(res=>{
    // res.data 才是真正的后端数据
    console.log(res.data.data.films)
    this.datalist = res.data.data.films
})


//post -1- x-www-form-urlencode
axios.post("json/test.json","name=zhangsan&age=10").then(res=>{
	console.log(res.data)
})

//post -2- application/json
axios.post("json/test.json",{
    name:"zhangsan",
    age:100
}).then(res=>{
    console.log(res.data)
})

组件使用

(1)组件化

模块化就是将系统功能分离成独立的功能部分的方法,一般指的是单个的某一种东西,例如js、css

而组件化针对的是页面中的整个完整的功能模块划分,组件是一个html、css、js、image等外链资源,这些部分组成的一个聚合体

优点:代码复用,便于维护

划分组件的原则:复用率高的,独立性强的

组件应该拥有的特性:可组合,可重用,可测试,可维护

(2)组件

在vue中,我们通过Vue.extend来创建Vue的子类,这个东西其实就是组件

也就是说Vue实例和组件的实例有差别但是差别不大,因为毕竟一个是父类一个是子类

一般的应用,会拥有一个根实例,在根实例里面都是一个一个的组件

因为组件是要嵌入到实例或者父组件里的,也就是说,组件可以互相嵌套,而且,所有的组件最外层必须有一个根实例,所以组件分为:全局组件和局部组件

全局组件在任意的实例、父级组件中都能使用,局部组件只能在创建自己的父级组件或者实例中使用

创建组件:

Vue.extend(options)

全局注册:

var App = Vue.extend({
	template:"<h1>hello world</h1>"
})
Vue.component('my-app',App)

简便写法:

// 创建组件构造器和注册组件合并一起  
Vue.component('hello',{//Vue会自动的将此对象给Vue.extend
	template:"<h1>hello</h1>"
})

组件通过template来确定自己的模板,template里的模板必须有根节点,标签必须闭合

组件的属性挂载通过:data方法来返回一个对象作为组件的属性,这样做的目的是为了每一个组件实例都拥有独立的data属性

局部注册:

new Vue({
    el:"#app",
    components:{
    	'my-app':App
    }
})

简便写法:

 data:{},
    components:{
        'hello':{
            template:"<h1>asdasdasdasdasdas</h1>"
        }
    }

在实例或者组件中注册另一个组件,这个时候,被注册的组件只能在注册它的实例或组件的模板中使用,一个组件可以被多个组件或实例注册

注意浏览器规则

因为vue在解析模板的时候会根据某些html的规则,例如,在table里只能放tr,td,th…,如果放入组件不会解析 这个时候我们可以放入tr使用is方式来标识这个tr其实是组件

<table id="app">
    <tr is="hello"></tr>
</table>

template

<template id="my-hello">
    <div>
        <h1>hello world</h1>
        <p>hahahah</p>
    </div>
</template>
//组件中
template:"#my-hello"

is切换

在实例、组件的模板中的某一个标签上,可以通过is属性来指定为另一个目标的组件,这个时候我们一般会使用component标签来占位、设置is属性来指定目标组件

<component :is="type"></component>

//组件中
data:{
    type:'aaa'
},
components:{
    'aaa':{template:"<h1>AAAAAAAAAAAAA</h1>"},
    'bbb':{template:"<h1>BBBBBBBBBBBBB</h1>"}
}

组件嵌套

应用中划分的组件可能会很多,为了更好的实现代码复用,所以必然会存在组件的嵌套关系

组件设计初衷就是要配合使用的,最常见的就是形成父子组件的关系:组件 A 在它的模板中使用了组件 B。

(3)过滤器

vue中可以设置filter(过滤器)来实现数据格式化,双花括号插值和 v-bind 表达式中使用

vue1.0的有默认的过滤器,但是在2.0的时候全部给去掉了

所以在vue中如果想要使用过滤器就需要自定义

自定义的方法有两种:全局定义和局部定义,
全局定义的过滤器在任意的实例、组件中都可以使用,
局部定义就是在实例、组件中定义,只能在这个实例或组件中使用

  1. 全局定义

    Vue.filter(name,handler)

    name是过滤器的名字,handler是数据格式化处理函数,接收的第一个参数就是要处理的数据,返回什么数据,格式化的结果就是什么

    在模板中通过 | (管道符) 来使用,在过滤器名字后面加()来传参,参数会在handler函数中第二个及后面的形参来接收

 <p>{{msg | firstUpper(3,2)}}</p>

Vue.filter('firstUpper',function (value,num=1,num2) {
	console.log(num2)
	return value.substr(0,num).toUpperCase()+value.substr(num).toLowerCase()
})
  1. 局部定义

    在实例、组件的配置项中设置 filters,键名为过滤器名,值为handler

    filters:{
        firstUpper:function (value,num=1,num2) {
        console.log(num2)
        return value.substr(0,num).toUpperCase()+value.substr(num).toLowerCase()
        }
    }

(4)虚拟dom

频繁且复杂的dom操作通常是前端性能瓶颈的产生点,Vue提供了虚拟dom的解决办法

虚拟的DOM的核心思想是:对复杂的文档DOM结构,提供一种方便的工具,进行最小化地DOM操作。这句话,也许过于抽象,却基本概况了虚拟DOM的设计思想

(1) 提供一种方便的工具,使得开发效率得到保证
(2) 保证最小化的DOM操作,使得执行效率得到保证

也就是说,虚拟dom的框架/工具都是这么做的:

  1. 根据虚拟dom树最初渲染成真实dom
  2. 当数据变化,或者说是页面需要重新渲染的时候,会重新生成一个新的完整的虚拟dom
  3. 拿新的虚拟dom来和旧的虚拟dom做对比(使用diff算法)。得到需要更新的地方之后,更新内容

这样的话,就能大量减少真实dom的操作,提高性能

什么是虚拟dom?与key值的关系?
Virual DOM是用JS对象记录一个dom节点的副本,当dom发生更改时候,先用
虚拟dom进行diff,算出最小差异,然后再修改真实dom。

当用传统的方式操作DOM的时候,浏览器会从构建DOM树开始从头到尾执行一遍流程,效率很低。而虚拟DOM是用javascript对象表示的,而操作javascript是很简便高效的。虚拟DOM和真正的DOM有一层映射关系,很多需要操作DOM的地方都会去操作虚拟DOM,最后统一一次更新DOM。因而可以提高性能

虚拟dom概括理解

虚拟dom与key的关系

发布了21 篇原创文章 · 获赞 0 · 访问量 292

猜你喜欢

转载自blog.csdn.net/weixin_43861707/article/details/104998934