对于 fetch 和 axios 和 Ajax 区别 ?

共享博客阅读(127)评论(0)

1.Ajax

Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。

用法:

$.ajax({
  type: 'POST',
  url: url,
  data: data,
  dataType: dataType,
  success: function() {},
  error: function() {}
});

优点:

  • 提高了性能和速度:减少了客户端和服务器之间的流量传输,同时减少了双方响应的时间,响应更快,因此提高了性能和速度
  • 交互性好:使用ajax,可以开发更快,更具交互性的Web应用程序
  • 异步调用:Ajax对Web服务器进行异步调用。这意味着客户端浏览器在开始渲染之前避免等待所有数据到达。
  • 节省带宽:基于Ajax的应用程序使用较少的服务器带宽,因为无需重新加载完整的页面
  • 底层使用XMLHttpRequest
  • 拥有开源JavaScript库 : JQuery,Prototype,Scriptaculous等。
  • AJAX通过HTTP协议进行通信

缺点:

  • 增加了设计和开发的时间
  • 比构建经典Web应用程序更复杂
  • Ajax应用程序中的安全性较低(容易收到CSRF和XSS攻击),因为所有文件都是在客户端下载的
  • 可能出现网络延迟的问题
  • 禁用javascript的浏览器无法使用该应用程序
  • 由于安全限制,只能使用它来访问服务于初始页面的主机的信息。如果需要显示来自其他服务器的信息,则无法在AJAX中显示。

2. axios

axios 基于promise用于浏览器和node.js的http客户端

用法:

axios({
    method: 'post',
    url: '/user/12345',
    data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
    }
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

优点:

  • 从node.js创建http请求
  • 在浏览器中创建XMLHttpRequest
  • 支持Promise API
  • 提供了一些并发请求的接口
  • 支持拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防御CSRF/XSRF

3.fetch

fetch号称是AJAX的替代品,是在ES6出现的,使用了ES6中的promise对象。Fetch是基于promise设计的。Fetch的代码结构比起ajax简单多了,参数有点像jQuery ajax。但是,一定记住fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。(然而问题还是有很多)

用法:

try {
  let response = await fetch(url);
  let data = response.json();
  console.log(data);
} catch(e) {
  console.log("Oops, error", e);
}

优点:

  • 符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象中
  • 更好更方便的写法
  • 更加底层,提供的API丰富(request,response)
  • 脱离了XHR,是ES规范里新的实现方式

缺点:

  • fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
  • fetch默认不会带cookie,需要添加配置项
  • fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject和Promise.race结合setTimeout实现的超时控制并不能阻止请求过程继续在后台执行,造成了量的浪费
  • fetch没有办法原生监测请求的进度,而XHR可以

 

vue中 不更新视图的处理办法?

共享博客阅读(159)评论(0)

方案一:利用Vue.set(object,key,val)

例:Vue.set(vm.obj,'key','value')

方案二:利用this.$set(this.obj,key,val)

例:this.$set(this.obj,'key','value')

方案三:利用Object.assign({},this.obj)创建新对象

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
 
Object.assign(target, ...sources)
 
参数
target
目标对象。
 
sources
源对象。
 
返回值
目标对象。
 
例:
 
const target = { a: 111, b: 2 };
const source = { b: 4, c: 5 };
 
const returnedTarget = Object.assign({},target, source);
 
console.log(target);
// expected output: Object { a: 111, b: 2}
 
console.log(returnedTarget);
// expected output: Object { a: 111, b: 4, c: 5 }

方法四:splice  替换  传三个参数 (开始下标,删除个数,替换内容)

this.tmpList.splice(index,1,'0');

 

vue是如何获取元素节点 ?

共享博客阅读(64)评论(0)

Js中:用document.getElement之类的语句来操作dom;
vue:使用vue提供的api,用 ref 来获取节点;

首先先用ref在元素上面做一个标记,然后用this.$refs.标记名来获取元素

代码:

<!DOCTYPE html>
<html>
 
<head>
  <meta charset="utf-8">
  <title>document</title>
  <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
 
<body>
  <div id="app">
    <span ref='pTag'>{{ message }}</span>
  </div>
 
  <script>
    new Vue({
      el: '#app',
      data() {
        return {
          message: 'hello 肾虚少年'
        }
      },
      mounted() {
        alert(this.$refs.pTag.innerHTML)
      }
    })
  </script>
</body>
 
</html>

vue2.0 对比 vue10 获取元素:

vue1.0 :版本中

在标签中加上el=’dom’,然后在代码中this.$els.dom这样就拿到了页面元素

例如:<div class=’box’  v-el: myBox>你好</div>

让你好的颜色显示为红色:this.$els.my-box.style.color = ‘red’

vue2.0:版本中

在标签中加上 ref=’dom’,然后在代码中this.$refs.dom这样就拿到了页面元素

例如:<div class=’box’ ref=’myBox’>你好</div>

让你好的颜色显示为红色:this.$refs.myBox.style.color = ‘red

Vue 组件间通信六种方式

共享博客阅读(59)评论(0)

前言

组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说,组件可以有以下几种关系: image

如上图所示,A 和 B、B 和 C、B 和 D 都是父子关系,C 和 D 是兄弟关系,A 和 C 是隔代关系(可能隔多代)。

针对不同的使用场景,如何选择行之有效的通信方式?这是我们所要探讨的主题。本文总结了vue组件间通信的几种方式,如props、$emit/$on、vuex、$parent / $children$attrs/$listeners和provide/inject,以通俗易懂的实例讲述这其中的差别及使用场景,希望对小伙伴有些许帮助。

方法一、props/$emit

父组件A通过props的方式向子组件B传递,B to A 通过在 B 组件中 $emit, A 组件中 v-on 的方式实现。

1.父组件向子组件传值

接下来我们通过一个例子,说明父组件如何向子组件传递值:在子组件Users.vue中如何获取父组件App.vue中的数据 users:["Henry","Bucky","Emily"]

//App.vue父组件
<template>
  <div id="app">
    <users v-bind:users="users"></users>//前者自定义名称便于子组件调用,后者要传递数据名
  </div>
</template>
<script>
import Users from "./components/Users"
export default {
  name: 'App',
  data(){
    return{
      users:["Henry","Bucky","Emily"]
    }
  },
  components:{
    "users":Users
  }
}
//users子组件
<template>
  <div class="hello">
    <ul>
      <li v-for="user in users">{{user}}</li>//遍历传递过来的值,然后呈现到页面
    </ul>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  props:{
    users:{           //这个就是父组件中子标签自定义名字
      type:Array,
      required:true
    }
  }
}
</script>

总结:父组件通过props向下传递数据给子组件。注:组件中的数据共有三种形式:data、props、computed

2.子组件向父组件传值(通过事件形式)

接下来我们通过一个例子,说明子组件如何向父组件传递值:当我们点击“Vue.js Demo”后,子组件向父组件传递值,文字由原来的“传递的是一个值”变成“子向父组件传值”,实现子组件向父组件值的传递。

子组件向父组件传值之前

 

// 子组件
<template>
  <header>
    <h1 @click="changeTitle">{{title}}</h1>//绑定一个点击事件
  </header>
</template>
<script>
export default {
  name: 'app-header',
  data() {
    return {
      title:"Vue.js Demo"
    }
  },
  methods:{
    changeTitle() {
      this.$emit("titleChanged","子向父组件传值");//自定义事件  传递值“子向父组件传值”
    }
  }
}
</script>
// 父组件
<template>
  <div id="app">
    <app-header v-on:titleChanged="updateTitle" ></app-header>//与子组件titleChanged自定义事件保持一致
   // updateTitle($event)接受传递过来的文字
    <h2>{{title}}</h2>
  </div>
</template>
<script>
import Header from "./components/Header"
export default {
  name: 'App',
  data(){
    return{
      title:"传递的是一个值"
    }
  },
  methods:{
    updateTitle(e){   //声明这个函数
      this.title = e;
    }
  },
  components:{
   "app-header":Header,
  }
}
</script>

总结:子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件。

方法二、$emit/$on

这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。当我们的项目比较大时,可以选择更好的状态管理解决方案vuex。

1.具体实现方式:

    var Event=new Vue();
    Event.$emit(事件名,数据);
    Event.$on(事件名,data => {});

2.举个例子

假设兄弟组件有三个,分别是A、B、C组件,C组件如何获取A或者B组件的数据

<div id="itany">
	<my-a></my-a>
	<my-b></my-b>
	<my-c></my-c>
</div>
<template id="a">
  <div>
    <h3>A组件:{{name}}</h3>
    <button @click="send">将数据发送给C组件</button>
  </div>
</template>
<template id="b">
  <div>
    <h3>B组件:{{age}}</h3>
    <button @click="send">将数组发送给C组件</button>
  </div>
</template>
<template id="c">
  <div>
    <h3>C组件:{{name}},{{age}}</h3>
  </div>
</template>
<script>
var Event = new Vue();//定义一个空的Vue实例
var A = {
	template: '#a',
	data() {
	  return {
	    name: 'tom'
	  }
	},
	methods: {
	  send() {
	    Event.$emit('data-a', this.name);
	  }
	}
}
var B = {
	template: '#b',
	data() {
	  return {
	    age: 20
	  }
	},
	methods: {
	  send() {
	    Event.$emit('data-b', this.age);
	  }
	}
}
var C = {
	template: '#c',
	data() {
	  return {
	    name: '',
	    age: ""
	  }
	},
	mounted() {//在模板编译完成后执行
	 Event.$on('data-a',name => {
	     this.name = name;//箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
	 })
	 Event.$on('data-b',age => {
	     this.age = age;
	 })
	}
}
var vm = new Vue({
	el: '#itany',
	components: {
	  'my-a': A,
	  'my-b': B,
	  'my-c': C
	}
});	
</script>

image $on 监听了自定义事件 data-a和data-b,因为有时不确定何时会触发事件,一般会在 mounted 或 created 钩子中来监听。

方法三、vuex

image

1.简要介绍Vuex原理

Vuex实现了一个单向数据流,在全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取State数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走Action,但Action也是无法直接修改State的,还是需要通过Mutation来修改State的数据。最后,根据State的变化,渲染到视图上。

2.简要介绍各模块在流程中的功能:

  • Vue Components:Vue组件。HTML页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
  • dispatch:操作行为触发方法,是唯一能执行action的方法。
  • actions:操作行为处理模块,由组件中的$store.dispatch('action 名称', data1)来触发。然后由commit()来触发mutation的调用 , 间接更新 state。负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。
  • commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
  • mutations:状态改变操作方法,由actions中的commit('mutation 名称')来触发。是Vuex修改state的唯一推荐方法。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。
  • state:页面状态管理容器对象。集中存储Vue components中data对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用Vue的细粒度数据响应机制来进行高效的状态更新。
  • getters:state对象读取方法。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。

3.Vuex与localStorage

vuex 是 vue 的状态管理器,存储的数据是响应式的。但是并不会保存起来,刷新之后就回到了初始状态,具体做法应该在vuex里数据改变的时候把数据拷贝一份保存到localStorage里面,刷新之后,如果localStorage里有保存的数据,取出来再替换store里的state。

let defaultCity = "上海"
try {   // 用户关闭了本地存储功能,此时在外层加个try...catch
  if (!defaultCity){
    defaultCity = JSON.parse(window.localStorage.getItem('defaultCity'))
  }
}catch(e){}
export default new Vuex.Store({
  state: {
    city: defaultCity
  },
  mutations: {
    changeCity(state, city) {
      state.city = city
      try {
      window.localStorage.setItem('defaultCity', JSON.stringify(state.city));
      // 数据改变的时候把数据拷贝一份保存到localStorage里面
      } catch (e) {}
    }
  }
})

这里需要注意的是:由于vuex里,我们保存的状态,都是数组,而localStorage只支持字符串,所以需要用JSON转换:

JSON.stringify(state.subscribeList);   // array -> string
JSON.parse(window.localStorage.getItem("subscribeList"));    // string -> array 

方法四、$attrs/$listeners

1.简介

多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。但如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点大材小用。为此Vue2.4 版本提供了另一种方法—-$attrs/$listeners

  • $attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件。通常配合 inheritAttrs 选项一起使用。
  • $listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件

接下来我们看个跨级通信的例子:

// index.vue
<template>
  <div>
    <h2>浪里行舟</h2>
    <child-com1
      :foo="foo"
      :boo="boo"
      :coo="coo"
      :doo="doo"
      title="前端工匠"
    ></child-com1>
  </div>
</template>
<script>
const childCom1 = () => import("./childCom1.vue");
export default {
  components: { childCom1 },
  data() {
    return {
      foo: "Javascript",
      boo: "Html",
      coo: "CSS",
      doo: "Vue"
    };
  }
};
</script>
// childCom1.vue
<template class="border">
  <div>
    <p>foo: {{ foo }}</p>
    <p>childCom1的$attrs: {{ $attrs }}</p>
    <child-com2 v-bind="$attrs"></child-com2>
  </div>
</template>
<script>
const childCom2 = () => import("./childCom2.vue");
export default {
  components: {
    childCom2
  },
  inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
  props: {
    foo: String // foo作为props属性绑定
  },
  created() {
    console.log(this.$attrs); // { "boo": "Html", "coo": "CSS", "doo": "Vue", "title": "前端工匠" }
  }
};
</script>
// childCom2.vue
<template>
  <div class="border">
    <p>boo: {{ boo }}</p>
    <p>childCom2: {{ $attrs }}</p>
    <child-com3 v-bind="$attrs"></child-com3>
  </div>
</template>
<script>
const childCom3 = () => import("./childCom3.vue");
export default {
  components: {
    childCom3
  },
  inheritAttrs: false,
  props: {
    boo: String
  },
  created() {
    console.log(this.$attrs); // { "coo": "CSS", "doo": "Vue", "title": "前端工匠" }
  }
};
</script>
// childCom3.vue
<template>
  <div class="border">
    <p>childCom3: {{ $attrs }}</p>
  </div>
</template>
<script>
export default {
  props: {
    coo: String,
    title: String
  }
};
</script>

image 如上图所示$attrs表示没有继承数据的对象,格式为{属性名:属性值}。Vue2.4提供了$attrs , $listeners 来传递数据与事件,跨级组件之间的通讯变得更简单。

简单来说:$attrs$listeners 是两个对象,$attrs 里存放的是父组件中绑定的非 Props 属性,$listeners里存放的是父组件中绑定的非原生事件。

方法五、provide/inject

1.简介

Vue2.2.0新增API,这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。一言而蔽之:祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系

2.举个例子

假设有两个组件: A.vue 和 B.vue,B 是 A 的子组件

// A.vue
export default {
  provide: {
    name: '浪里行舟'
  }
}
// B.vue
export default {
  inject: ['name'],
  mounted () {
    console.log(this.name);  // 浪里行舟
  }
}

可以看到,在 A.vue 里,我们设置了一个 provide: name,值为 浪里行舟,它的作用就是将 name 这个变量提供给它的所有子组件。而在 B.vue 中,通过 inject 注入了从 A 组件中提供的 name 变量,那么在组件 B 中,就可以直接通过 this.name 访问这个变量了,它的值也是 浪里行舟。这就是 provide / inject API 最核心的用法。

需要注意的是:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的—-vue官方文档 所以,上面 A.vue 的 name 如果改变了,B.vue 的 this.name 是不会改变的,仍然是 浪里行舟。

3.provide与inject 怎么实现数据响应式

一般来说,有两种办法:

  • provide祖先组件的实例,然后在子孙组件中注入依赖,这样就可以在子孙组件中直接修改祖先组件的实例的属性,不过这种方法有个缺点就是这个实例上挂载很多没有必要的东西比如props,methods
  • 使用2.6最新API Vue.observable 优化响应式 provide(推荐)

我们来看个例子:孙组件D、E和F获取A组件传递过来的color值,并能实现数据响应式变化,即A组件的color变化后,组件D、E、F会跟着变(核心代码如下:)

image

// A 组件 
<div>
      <h1>A 组件</h1>
      <button @click="() => changeColor()">改变color</button>
      <ChildrenB />
      <ChildrenC />
</div>
......
  data() {
    return {
      color: "blue"
    };
  },
  // provide() {
  //   return {
  //     theme: {
  //       color: this.color //这种方式绑定的数据并不是可响应的
  //     } // 即A组件的color变化后,组件D、E、F不会跟着变
  //   };
  // },
  provide() {
    return {
      theme: this//方法一:提供祖先组件的实例
    };
  },
  methods: {
    changeColor(color) {
      if (color) {
        this.color = color;
      } else {
        this.color = this.color === "blue" ? "red" : "blue";
      }
    }
  }
  // 方法二:使用2.6最新API Vue.observable 优化响应式 provide
  // provide() {
  //   this.theme = Vue.observable({
  //     color: "blue"
  //   });
  //   return {
  //     theme: this.theme
  //   };
  // },
  // methods: {
  //   changeColor(color) {
  //     if (color) {
  //       this.theme.color = color;
  //     } else {
  //       this.theme.color = this.theme.color === "blue" ? "red" : "blue";
  //     }
  //   }
  // }
// F 组件 
<template functional>
  <div class="border2">
    <h3 :style="{ color: injections.theme.color }">F 组件</h3>
  </div>
</template>
<script>
export default {
  inject: {
    theme: {
      //函数式组件取值不一样
      default: () => ({})
    }
  }
};
</script>

虽说provide 和 inject 主要为高阶插件/组件库提供用例,但如果你能在业务中熟练运用,可以达到事半功倍的效果!

方法六、$parent / $childrenref

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
  • $parent / $children:访问父 / 子实例

需要注意的是:这两种都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据。我们先来看个用 ref来访问组件的例子:

// component-a 子组件
export default {
  data () {
    return {
      title: 'Vue.js'
    }
  },
  methods: {
    sayHello () {
      window.alert('Hello');
    }
  }
}
// 父组件
<template>
  <component-a ref="comA"></component-a>
</template>
<script>
  export default {
    mounted () {
      const comA = this.$refs.comA;
      console.log(comA.title);  // Vue.js
      comA.sayHello();  // 弹窗
    }
  }
</script>

不过,这两种方法的弊端是,无法在跨级或兄弟间通信

// parent.vue
<component-a></component-a>
<component-b></component-b>
<component-b></component-b>

我们想在 component-a 中,访问到引用它的页面中(这里就是 parent.vue)的两个 component-b 组件,那这种情况下,就得配置额外的插件或工具了,比如 Vuex 和 Bus 的解决方案。

总结

常见使用场景可以分为三类:

  • 父子通信: 父向子传递数据是通过 props,子向父是通过 events($emit);通过父链 / 子链也可以通信($parent / $children);ref 也可以访问组件实例;provide / inject API;$attrs/$listeners
  • 兄弟通信: Bus;Vuex
  • 跨级通信: Bus;Vuex;provide / inject API、$attrs/$listeners

vue核心面试题:组件中的data为什么是一个函数

共享博客阅读(70)评论(0)

一、总结

1.vue中组件是用来复用的,为了防止data复用,将其定义为函数。

2.vue组件中的data数据都应该是相互隔离,互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响,就需要通过data函数返回一个对象作为组件的状态。

3.当我们将组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,拥有自己的作用域,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。

4.当我们组件的date单纯的写成对象形式,这些实例用的是同一个构造函数,由于JavaScript的特性所导致,所有的组件实例共用了一个data,就会造成一个变了全都会变的结果。

二、代码分析:

vue每次会通过组件创建出一个构造函数,每个实例都是通过这个构造函数new出来的

假如data是一个对象,将这个对象放到这个放到原型上去

function VueComponent(){}
VueComponent.prototype.$options = {
    data:{name:'three'} 
}
let vc1 = new VueComponent();
vc1.$options.data.name = 'six'; // 将vc1实例上的data修改为six
let vc2 = new VueComponent(); // 在new一个新的实例vc2
console.log(vc2.$options.data.name); six
// 输出vc2的data的值是six,这时候发现vc2中的data也被修改了,他们data相互影响

将data改为一个函数

// 这样就可以保证每个组件调用data返回一个全新的对象,和外部没有关系
function VueComponent(){}
VueComponent.prototype.$options = {
    data: () => ({name:'three'}) 
}
let vc1 = new VueComponent();
let objData = vc1.$options.data()
objData.name = 'six'; // 调用data方法会返回一个对象,用这个对象作为它的属性
console.log(objData)
let vc2 = new VueComponent();
console.log(vc2.$options.data());

三、源码

1.在core/global-api/extend.js中会调用mergeOptions方法

    const Sub = function VueComponent (options) {
      this._init(options)
    } // 创建一个子类
    Sub.prototype = Object.create(Super.prototype)
    Sub.prototype.constructor = Sub
    Sub.cid = cid++    
    Sub.options = mergeOptions( // 调用mergeOptions进行合并
      Super.options,
      extendOptions
    )
    Sub.extend = Super.extend
    Sub.mixin = Super.mixin
    Sub.use = Super.use

2.mergeOptions方法(src/core/util/options.js)

// 将两个对象合并到一个对象中
// 包括生命周期的合并,data的合并等
export function mergeOptions (
  parent: Object,
  child: Object,
  vm?: Component
): Object {
  if (process.env.NODE_ENV !== 'production') {
    checkComponents(child)
  }
 
  if (typeof child === 'function') {
    child = child.options
  }
 
  normalizeProps(child, vm)
  normalizeInject(child, vm)
  normalizeDirectives(child)
  if (!child._base) {
    // 对extend和mixins做合并
    if (child.extends) {
      parent = mergeOptions(parent, child.extends, vm)
    }
    if (child.mixins) {
      for (let i = 0, l = child.mixins.length; i < l; i++) {
        parent = mergeOptions(parent, child.mixins[i], vm)
      }
    }
  }
 
  const options = {}
  let key
  // 循环父类
  for (key in parent) {
    mergeField(key)
  }
  // 循环子类
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
  }
  // 合并字段
  function mergeField (key) {
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }
  return options
}

3.合并data(src/core/util/options.js)

strats.data = function (
  parentVal: any,
  childVal: any,
  vm?: Component
): ?Function {
  if (!vm) {
    // 合并之前看看这个子类是不是一个函数,如果不是就告诉他这个数据应该是一个函数
    // 因为每一个组件都会返回一个实例
    if (childVal && typeof childVal !== 'function') {
      process.env.NODE_ENV !== 'production' && warn(
        'The "data" option should be a function ' +
        'that returns a per-instance value in component ' +
        'definitions.',
        vm
      )
 
      return parentVal
    }
    // 如果是函数就调用mergeDataOrFn进行合并
    return mergeDataOrFn(parentVal, childVal)
  }
 
  return mergeDataOrFn(parentVal, childVal, vm)
}

4.源码总结:

通过vue.extend方法创建一个子类,创建子类之后会把自己的选项和父类的选项使用mergeOptions方法做一个合并,自己的选项就包含data。在mergeOptions中会调用strats.data对子类的data进行合并,这个方法中首先会判断子类的data进行判断,要求data必须是一个函数,如果不是会报错告诉它这个data应该是一个函数定义,因为每一个组件都会返回一个实例,如果是data就会调用 mergeDataOrFn方法进行合并。然后会合并父类的extend、minin、use方法,最后extend返回的就是这个子类的方法。

补充:

为什么要合并?因为子组件也要有父组件的属性,extend方法是通过一个对象创建了一个构造函数,但是这个构造函数并没有父类的属性,因为它是一个新函数,和之前的Vue构造函数是没有关系的。通过extend产生了一个子函数,这个子函数需要拥有vue实例上的所以东西,它就要做一次合并。

四、为什么new Vue这个里面的data可以放一个对象?

因为这个类创建的实例不会被复用。它只会new一次,不用考虑复用。

 

vuex的mutation和action的区别和使用

共享博客阅读(68)评论(0)

mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

this.$store.commit(“mutation函数名”,发送到mutation中的数据)

Action

actions函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

this.$store.dispatch(‘action中的函数名’,发送到action中的数据)

在action中提交mutation :

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {    //官方给出的指定对象, 此处context可以理解为store对象
      context.commit('increment');
    }
  }
})

actions的不同写法

// 第一种写法简写形式
  const actions = {
    action的函数名({commit}) { 
      commit(“mutation函数名”, value);   //调用mutation中的函数
      //此处value可以是对象,可以是固定值等
    }
  }
  // 第二种形式
  const actions = {
    action中的函数名(context) {
      //context 官方给出的指定对象, 此处context可以理解为store对象
      context.commit(“mutation函数名”, value);     //调用mutation中的函数
    }
  }

1、流程顺序

“相应视图—>修改State”拆分成两部分,视图触发Action,Action再触发Mutation。

2、角色定位

基于流程顺序,二者扮演不同的角色。

Mutation:专注于修改State,理论上是修改State的唯一途径。

Action:业务代码、异步请求。

3、限制

角色不同,二者有不同的限制。

Mutation:必须同步执行。

Action:可以异步,但不能直接操作State。而且可以通过 action 来提交 mutations

小程序里面的双向绑定和vue中的双向绑定有什么区别?

共享博客阅读(87)评论(0)

小程序中的数据双向绑定
    . 首先通过 bindinput 绑定文本框的输入事件
    . 在 data 中声明一个变量 content ,将其动态绑定成文本框的 value 值
    . 在 bindinput 事件中通过事件参数 e.detail.value 可以获取到文本框中最新的 value 值
    . 通过 this.setData 将文本框最新的  value 值 赋值给 动态绑定的value值 content  即可实现数据的双向绑定

vue中的数据双向绑定
    . 首先为文本框绑定 @input 监听文本框的输入事件
    . 为文本框动态绑定 value 属性,其值是在data中定义的变量
    . 在 @input绑定的事件中 通过事件参数 event.target.value 可以获取到 input 框中最新的value值
    . 将其重新获取到的 value 赋值给 value值动态绑定的那个变量

区别:
大体上区别不大,绑定事件不同,以及获取value值的具体方式不同,以及在小程序中设置data中的数据,需要调用 this.setData方法进行设置

在vue中进行数据绑定后,当数据修改了会直接更新到视图上,但是在小程序中呢,data数据修改是不会直接同步到,必须调用this.setData()这个方法

例:


data:{
 arr:[{name:"小李"},{name:"小王"}],
 list:[{name:"小明"},{name:"小红"}]
},
setMsg(){  //该方法可以绑定到事件上也可以在onLoad里面调用  
  this.data.arr = this.data.list
   this.setData({
    arr:this.data.arr, // 简单粗暴直接修改
    ["list[0].name"]:"小张"  //也可以只修改里面的一项,
   })
}

 

Vue3.0 起跑 搭建项目后应用 系列二

共享博客阅读(248)评论(1)

Vue3.0部分知识点

项目目录结构

|-node_modules       -- 所有的项目依赖包都放在这个目录下
|-public             -- 公共文件夹
---|favicon.ico      -- 网站的显示图标
---|index.html       -- 入口的html文件
|-src                -- 源文件目录,编写的代码基本都在这个目录下
---|assets           -- 放置静态文件的目录,比如logo.pn就放在这里
---|components       -- Vue的组件文件,自定义的组件都会放到这
---|App.vue          -- 根组件,这个在Vue2中也有
---|main.ts          -- 入口文件,因为采用了TypeScript所以是ts结尾
---|shims-vue.d.ts   -- 类文件(也叫定义文件),因为.vue结尾的文件在ts中不认可,所以要有定义文件
|-.browserslistrc    -- 在不同前端工具之间公用目标浏览器和node版本的配置文件,作用是设置兼容性
|-.eslintrc.js       -- Eslint的配置文件,不用作过多介绍
|-.gitignore         -- 用来配置那些文件不归git管理
|-package.json       -- 命令配置和包管理文件
|-README.md          -- 项目的说明文件,使用markdown语法进行编写
|-tsconfig.json      -- 关于TypoScript的配置文件
|-yarn.lock          -- 使用yarn后自动生成的文件,由Yarn管理,安装yarn包时的重要信息存储到yarn.lock文件中  

1. package.json三个命令

{
"scripts": {
    "serve": "vue-cli-service serve",   在开发时用于查看效果的命令,视频中演示看一下效果
    "build": "vue-cli-service build",   打包打码,一般用于生产环境中使用
    "lint": "vue-cli-service lint"      检查代码中的编写规范
},
开发环境 devDependencies 编写代码、测试代码、修改 Bug。也就说这些代码没有上线。
测试环境 dependencies    就是代码已经上线,放到了正式的服务器上。
}

2. main.ts文件

import { createApp } from "vue"; // 引入vue文件,并导出`createApp`
import App from "./App.vue"; // 引入自定义组件,你在页面上看的东西基本都在这个组件里

createApp(App).mount("#app"); // 把App挂载到#app节点上,在public目录下的index.html找节点

setup() ref()

setup() //代替data和method返回数据和方法,在beforeCreate、created之前执行
setup()函数的用法,可以代替 Vue2 中的 date 和 methods 属性,直接把逻辑卸载 setup 里就可以

ref 函数的使用,它是一个神奇的函数,要在template中使用的变量,必须用ref包装一下。
return出去的数据和方法,在模板中才可以使用,这样可以精准的控制暴漏的变量和方法。

defineComponent重载函数

<script lang="ts">
    import { defineComponent, ref } from "vue";
    export default defineComponent({
    name: "App",
    setup() {
        const aa = ref(["11", "22", "33"]); //无初始值设置为null
        return {
        aa
        };

    <!-- const divs = ref([])
        组件挂载后,即能通过divs.value获取遍历元素的所有dom
        return{
            divs
    } -->

    },
    });
</script>
```html
# reactive()函数优化
    reactive()函数接收一个普通对象,返回一个响应式的数据对象。用户数据生成代理对象,从而实现监控用户数据改变的目的。
```html
<script lang="ts">
    import { ref, reactive } from "vue";
    export default {
    name: "App",
    setup() {
        const data = reactive({
        const aa = ref(["11", "22", "33"]);
        });

        return {
        data,
        };
    },
    };
</script>
ref(),reactive() //定义vue2.0中data和method方法

toRefs()优化

toRefs()函数可以将reactive()创建出来的响应式对象,转换为普通对象,只不过这个对象上的每个属性节点,都是ref()类型的响应式数据
toRefs() //使用拓展用算符…的方法返回数据data

import { reactive, toRefs } from "vue";
export default {
name: "App",
setup() {
    const data: DataProps = reactive({
    const aa = ref(["11", "22", "33"]);
    });
    const refData = toRefs(data);
    return {
    ...refData,
    };
},
};

watch-监听器(侦听器)

(1)不会立即执行,当侦听的源变更时才会执行
(2)可以监听多个数据源

import {… , watch} from “vue” 引入后编写watch函数,它接受两个参数,第一个是要监听的值overText,然后是一个回调函数。在函数中你可以获得到新知和老值。
定义一个方法
使用watch同样需要先进行导入.

import { watch } from 'vue'
const overAction = () => {
overText.value = overText.value;
};
return {  overAction};
}
watch(aa, (newValue, oldValue) => {
document.title = newValue;
});

如果监听多个值
watch([overText, () => data.select], (newValue, oldValue) => {
console.log(`new--->${newValue}`);
console.log(`old--->${oldValue}`);
document.title = newValue[0];
});

vue3生命周期

setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method

onBeforeMount() : 组件挂载到节点上之前执行的函数。
onMounted() : 组件挂载完成后执行的函数。
onBeforeUpdate(): 组件更新之前执行的函数。
onUpdated(): 组件更新完成之后执行的函数。
onBeforeUnmount(): 组件卸载之前执行的函数。
onUnmounted(): 组件卸载完成后执行的函数
onActivated(): 被包含在<keep-alive>中的组件,会多出两个生命周期钩子函数。被激活时执行。
onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行。
onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数(以后用到再讲,不好展现)。

注:使用组件会将数据保留在内存中,比如我们不想每次看到一个页面都重新加载数据,就可以使用组件解决。

先列举5个常用得

<script lang="ts">
import {
reactive,
toRefs,
onMounted,
onBeforeMount,
onBeforeUpdate,
onUpdated,
} from "vue";

const app = {
name: "App",
setup() {
    const data: DataProps = reactive({
    const aa = ref(["11", "22", "33"]);
    });
    onBeforeMount(() => {
    console.log("2-组件挂载到页面之前执行-----onBeforeMount()");
    });
    onMounted(() => {
    console.log("3-组件挂载到页面之后执行-----onMounted()");
    });
    onBeforeUpdate(() => {
    console.log("4-组件更新之前-----onBeforeUpdate()");
    });
    onUpdated(() => {
    console.log("5-组件更新之后-----onUpdated()");
    });
    const refData = toRefs(data);
    return {
    ...refData,
    };
},
};
export default app;

结果:

1 - 开始创建组件---- - setup();
2 - 组件挂载到页面之前执行---- - onBeforeMount();
3 - 组件挂载到页面之后执行---- - onMounted();
4 - 组件更新之前---- - onBeforeUpdate();
5 - 组件更新之后---- - onUpdated();

vue2得生命周期在vue3 也可以用 但是不愿混用

你可以在setup()函数之后编写Vue2的生命周期函数,代码如下:

beforeCreate() {
console.log("1-组件创建之前-----beforeCreate()");
},
beforeMount() {
console.log("2-组件挂载到页面之前执行-----BeforeMount()");
},
mounted() {
console.log("3-组件挂载到页面之后执行-----Mounted()");
},
beforeUpdate() {
console.log("4-组件更新之前-----BeforeUpdate()");
},
updated() {
console.log("5-组件更新之后-----Updated()");
},

Vue2.x 与 Vue3.x的生命周期钩子函数

Vue2--------------vue3
beforeCreate  -> setup()
created       -> setup()
beforeMount   -> onBeforeMount
mounted       -> onMounted
beforeUpdate  -> onBeforeUpdate
updated       -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed     -> onUnmounted
activated     -> onActivated
deactivated   -> onDeactivated
errorCaptured -> onErrorCaptured

钩子函数的使用

1. onRenderTracked直译过来就是状态跟踪——-散弹枪

它会跟踪页面上所有响应式变量和方法的状态,也就是我们用return返回去的值,他都会跟踪。只要页面有update的情况,他就会跟踪,然后生成一个event对象,我们通过event对象来查找程序的问题所在。

使用onRenderTracked同样要使用import进行引入。
import { .... ,onRenderTracked,} from "vue";

引用后就可以在setup()函数中进行引用了。
onRenderTracked((event) => {
console.log("状态跟踪组件----------->");
console.log(event);
});

在组件没有更新的时候onRenderTracked是不会执行的,组件更新时,他会跟组里边每个值和方法的变化。

2. onRenderTriggered直译过来是状态触发——-狙击枪

它不会跟踪每一个值,而是给你变化值的信息,并且新值和旧值都会给你明确的展示出来。 
import { .... ,onRenderTriggered,} from "vue";

onRenderTriggered()函数,写在setup()函数里边,
onRenderTriggered((event) => {
console.log("状态触发组件--------------->");
console.log(event);
});

对 event 对象属性的详细介绍:

- key 那边变量发生了变化
- newValue 更新后变量的值
- oldValue 更新前变量的值
- target 目前页面中的响应变量和函数

vue3模块化

1. 新建一个ts文件

直接上代码,在src目录下,新建一个文件夹host(所有抽离出来的功能模块都可以放到这个文件夹里),然后再新建一个ts文件

import { ref } from "vue";    //在代码的最前面用import进行引入ref
const nowTime = ref("00:00:00");
const getNowTime = () => {
    const now = new Date();
    const hour = now.getHours() < 10 ? "0" + now.getHours() : now.getHours();
    const minu =
        now.getMinutes() < 10 ? "0" + now.getMinutes() : now.getMinutes();
    const sec =
        now.getSeconds() < 10 ? "0" + now.getSeconds() : now.getSeconds();
    nowTime.value = hour + ":" + minu + ":" + sec;

    setTimeout(getNowTime, 1000);
};
export { nowTime, getNowTime } //,在最后用export的方式

2.APP.vue页面

引入代码:

<template>
<div>
    <div>{{ nowTime }}</div>
    <div><button @click="getNowTime">显示时间</button></div>
</div>
</template>
<script lang="ts">
import { nowTime, getNowTime } from "./host/useNowTime"

import {
    defineComponent,
    ref,
} from 'vue';
export default defineComponent({
    name: 'App',
    components: {
    },
    setup() {
        return{
            nowTime,getNowTime
        }
    }
});
</script>

简单的弹框组件

1.在/src/components/目录下,创建一个Dialog.vue的组件

<template>
<div id="center">
    <h2>显示的内容</h2>
</div>
</template>
<script lang="ts">
export default {};
</script>
<style>
#center {
width: 200px;
height: 200px;
border: 2px solid black;
background: white;
position: fixed;
left: 50%;
top: 50%;
margin-left: -100px;
margin-top: -100px;
}
</style>

2.在App.vue中使用

import modal from "./components/Dialog.vue";
const app = {
	 name: "App",
	 components: {
	     Dialog,
	 },
}

Suspense组件的使用

使用方法一:<Suspense></Suspense>与插槽配合
Suspense是有两个template插槽的,第一个default代表异步请求完成后,显示的模板内容。fallback代表在加载中时,显示的模板内容。

1.1定义组件

<template>
<h1>{{result}}</h1>
</template>
<script>
export default {
    name: "NewModel",
    setup(){
        return new Promise((resolve)=>{
            setTimeout(()=>{
                return resolve({result:"OK"})
            },3000)
        })
    }
}
</script>

1.2使用suspense组件渲染效果

<suspense>
    <template #default>
        <new-model></new-model>
    </template>
    <template #fallback>
        <h1>Loadding...</h1>
    </template>
</suspense>

结果三秒之前显示Loadding… ,三秒之后显示组件内容;(成功后显示组件内容)

2.1定义异步组件

Suspense也是支持async…await的语法的,所以这个组件就用async的写法来写。

<template>
    <img :src="result%20&&%20result.imgUrl"  />
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
    async setup() {  //promise 语法糖  返回之后也是promise对象
        const rawData = await  axios.get('https://apiblog.jspang.com/default/getGirl')
        return {result:rawData.data}
    }
})

2.2 引入组件使用

导入组件  注册组件后
<template>
<div>
    <Suspense>
    <template #default>
        <girl-show />
    </template>
    <template #fallback>
        <h1>Loading...</h1>
    </template>
    </Suspense>
</div>
</template>

3. 异步错误处理

可以使用onErrorCaptured这个钩子函数来捕获异常
引入. import { ref , onErrorCaptured} from “vue”;
有了onErrorCaptured就可以直接在setup()函数中直接使用了。钩子函数要求我们返回一个布尔值,代表错误是否向上传递。

setup() {
    onErrorCaptured((error) => {
    console.log(`error====>`,error)
    return true  
    })
    return {};
},
<template>
    <template #fallback>
        <h1>Loading...</h1>
    </template>
    </Suspense>
</div>
</template>

3. 异步错误处理

可以使用onErrorCaptured这个钩子函数来捕获异常
引入. import { ref , onErrorCaptured} from “vue”;
有了onErrorCaptured就可以直接在setup()函数中直接使用了。钩子函数要求我们返回一个布尔值,代表错误是否向上传递。

setup() {
    onErrorCaptured((error) => {
    console.log(`error====>`,error)
    return true  
    })
    return {};
},
</script>

 

VSCode打造成为开发神器

共享博客阅读(196)评论(0)

VSCode现在是世界上最为常用的编辑器之一,为什么被称为编辑器,是因为它不像IDE一样集成了大量开发环境的配置,必须你手动配置很多东西,才能将它打造成为一个趁手的生产工具。

VSCode最大的优势就在于它是完全免费的,你不需要支付任何费用,就可以得到一个开发各种代码的编辑器,也正因为它具有高拓展性,它可以用来编写Python、C++、C#、GO、Dart等一系列语言。

你可以通过下面的插件将VSCode打造成为一个趁手的开发神器:

1. 编程语言类

下面的几个插件根据情况安装。

C/C++

Dart

dart-import

Go

Go Doc

Python

2. 代码风格类

Beautify:格式化代码插件,不过现在更推荐使用Prettier。

Prettier – Code formatter:当前前端最火的格式化代码插件。

Better Align:对齐代码。

Better Comments:更好的注释提示插件,推荐使用。

change-case:驼峰命名、下划线命名等等命名规则进行相互转化。

ESLint:团队开发的时候统一代码风格神器,以防因为代码风格不同而造成代码冲突。

Guides:代码块提示。

SonarLint:代码质量检测,和ESLint兼容,不会出现相互冲突的规则。

3. 代码提示类

3.1 Angular

开发Angular需要的插件。

Angular Snippets (Version 11)

3.2 React

开发React需要的插件。

ES7 React/Redux/GraphQL/React-Native snippets

React Native Tools

3.3 Vue

开发Vue需要的插件。

Vetur

vue

Vue 3 Snippets

Vue Peek

Vue VSCode Snippets

3.4 HTML

Auto Close Tag:自动闭合HTML标签。

Auto Rename Tag:更改一个HTML标签其对应的另一个标签也会被同时更改。

3.5 JavaScript/TypeScript

下面两个插件都为自动引入插件,只需要在文件中输入已经导出的函数名,就会自动添加引入代码!推荐使用!

Auto Import

TypeScript Hero

JavaScript (ES6) code snippets:快速生成代码片段。

3.6 CSS

Color Highlight:颜色高亮插件。

Color Picker:颜色选择插件。

CSS Peek:可以定位到项目中已经声明过的CSS类。

px to rem:将px转化为rem。

Tailwind CSS IntelliSense:原子化CSS库Tailwind的代码提示。

3.7 Flutter

开发Flutter需要的插件。

Flutter

Awesome Flutter Snippets

Flutter Widget Snippets

3.8 小程序

开发小程序需要的插件。

minapp

3.9 其它

Bookmarks:可以在代码中设置书签。

Bracket Pair Colorizer 2:将不同的括号显示不同的颜色。

HTML CSS Support:完成HTML和CSS。

HTML Snippets:HTML片段。

Image preview:引入项目中的图片预览。

Import Cost:检测导入项目中的包的大小,在优化项目的时候非常有用。

JavaScript Booster:将箭头函数和普通函数进行相互转换。

TODO Highlight:将注释中的TODO进行高亮。

Todo Tree:自动跳转到注释中含有TODO的地方。

3.10 慎用系列

IntelliSense for CSS class names in HTML:在编写HTML时获得CSS文件中的类名提示。

注:在开启该插件后,VSCode会有一个很长的文件搜索时间,不推荐使用。

koroFileHeader:在文件头部生成注释,并且能够一键生成函数JSDOC注释。

注:有时候会觉得自动生成比较烦,所以我暂时没有使用。

Live Sass Compiler:将Sass文件转换为CSS文件。

注:在不使用框架的情况下开发项目非常有用,但是使用框架后就不需要将Sass文件转为CSS文件。

Sass/Less/Stylus/Pug/Jade/Typescript/Javascript Compile Hero Pro:同上,只是转化的文件类型更多样。

4. 编辑器拓展

4.1 Cocos-creator

让VSCode能够成为Cocos开发工具,cocos-creator目前主要用来做H5游戏。

Cocos Debug

cocos-creator

4.2 主题

Atom One Dark Theme

One Dark Pro

vscode-icons:将VSCode左侧文件预览图标变得多样化。

4.3 语言包

Chinese (Simplified) Language Pack for Visual Studio Code:VSCode中文语言包。

4.4 工具

Browser Preview:使VSCode内嵌一个浏览器窗口。

Code Runner:使VSCode具有直接运行各种编程语言的能力。

Code Spell Checker:检测项目中的单词是否有拼写上的错误。

Debugger for Chrome:能够使VSCode在Chrome上面调试代码。

Debugger for Firefox:能够使VSCode在Firefox上面调试代码。

Docker:使VSCode具有操控Docker的功能。

Draw.io Integration:可以在VSCode中创建流程图。

Gist:使VSCode能够快速创建Gist代码片段。

Git History:可以快速的查看到Git提交历史。

gitignore:快速生成gitignore文件。

GitLens — Git supercharged:使VSCode具有Git管理功能。

Kite AutoComplete AI Code:根据你写的代码,AI自动推测你接下来可能要写的代码。

Live Server:能够启动一个服务器,当代码进行变动时自动刷新浏览器,主要是用于原生开发。

npm:检测项目中的package.json文件,可以通过该插件快速启动项目。

npm Intellisense:自动完成导入模块名称。

open in browser:快速在浏览器中打开HTML文件。

Partial Diff:快速比较两段代码的不同之处。

Paste JSON as Code:自动将JSON文件转化为TypeScript、C#等等各种语言的声明代码。

Path Intellisense:引入文件时具有文件地址提示。

Project Manager:项目管理,如果有几个经常需要打开的项目,就可以使用该插件,可以非常方便的切换项目。

Quokka.js:调试插件。

作者:沧沧凉凉

2021 年你应该尝试的 8 个 React 库

共享博客阅读(189)评论(1)

2021 年你应该尝试的 8 个 React 库插图

 

1. react-select

2021 年你应该尝试的 8 个 React 库插图1

一个厉害的,强大的表单下拉选择框的库

代表了一种开发功能强大的 react.js 组件的全新方式,这些组件在完全可定制的同时开箱即用。

突出的功能特性

  • 灵活的数据处理方法,具有可定制的功能。
  • 灵活结合 emotion 这个库**(一个 css in js 的强大的库** ).
  • 组件注入API,用于完全控制UI行为。
  • 选项组、portal 支持、动画等。

安装:

npm i react-select

示例代码:

import React, { Component } from 'react'
import Select from 'react-select'

const options = [
  { value: 'chocolate', label: 'Chocolate' },
  { value: 'strawberry', label: 'Strawberry' },
  { value: 'vanilla', label: 'Vanilla' }
]

const MyComponent = () => (
  <Select options={options} />
)

2. react-dnd

2021 年你应该尝试的 8 个 React 库插图2

React 的拖拽包

一个强大的工具包,能够做出丰富的拖拽页面应用,而且代码具有解耦性。

突出的功能

  • 非常适合Trello(一个管理任务的工具)和Storify 等应用程序,其中拖动负责在应用程序的不同部分之间传输数据。
  • 建立在HTML5拖放API之上。

安装:

npm i react-dnd

示例代码:

import React from 'react'
import { useDrag } from 'react-dnd'
import { ItemTypes } from './Constants'

/**
 * Your Component
 */
export default function Card({ isDragging, text }) {
  const [{ opacity }, dragRef] = useDrag({
    item: { type: ItemTypes.CARD, text },
    collect: (monitor) => ({
      opacity: monitor.isDragging() ? 0.5 : 1
    })
  })
  return (
    <div ref={dragRef} style={{ opacity }}>
      {text}
    </div>
  )
}

3. react-content-loader

2021 年你应该尝试的 8 个 React 库插图3

基于 SVG 的强大的组件库,可以轻易地创造骨架式的 加载页面(loading)(有点像 Facebook 的卡片加载)

突出的功能

  • 很多插件: 有许多预设可供使用。
  • DIY: 您可以使用create-content-loader轻松创建自己的加载程序。
  • React Native 支持: 具有相同强大功能的相同API。
  • 轻易: 包小于 2KB and 零依赖

安装:

npm i react-content-loader

示例代码:

import React from "react"
import ContentLoader from "react-content-loader"

const MyLoader = (props) => (
  <ContentLoader 
    speed={2}
    width={400}
    height={160}
    viewBox="0 0 400 160"
    backgroundColor="#f3f3f3"
    foregroundColor="#ecebeb"
    {...props}
  >
    <rect x="48" y="8" rx="3" ry="3" width="88" height="6" /> 
    <rect x="48" y="26" rx="3" ry="3" width="52" height="6" /> 
    <rect x="0" y="56" rx="3" ry="3" width="410" height="6" /> 
    <rect x="0" y="72" rx="3" ry="3" width="380" height="6" /> 
    <rect x="0" y="88" rx="3" ry="3" width="178" height="6" /> 
    <circle cx="20" cy="20" r="20" />
  </ContentLoader>
)

export default MyLoader

4. antd

2021 年你应该尝试的 8 个 React 库插图4

企业级用户界面设计语言和React UI库。

突出的功能

  • 使用 TypeScript 编写
  • 一整套设计资源和开发工具。
  • 每个细节都有强大的主题定制。

安装:

npm i antd

示例代码:

import { useRequest } from 'umi';
import { queryProductList } from '@/services/product';

export default function useProductList(params: { pageSize: number; current: number }) {
  const msg = useRequest(() => queryUserList(params));

  const deleteProducts = async (id: string) => {
    try {
      await removeProducts(id);
      message.success('success');
      msg.run();
    } catch (error) {
      message.error('fail');
    }
  };

  return {
    dataSource: msg.data,
    reload: msg.run,
    loading: msg.loading,
    deleteProducts,
  };
}

5. gatsby-image

使用 React构建快速、现代的应用程序和网站

突出的功能

  • 以极低代价托管: Gatsby站点不需要服务器,因此您可以以服务器呈现站点的一小部分成本在CDN上托管整个站点。
  • 从任何地方定位数据: 从任何数据源 (Markdown文件,像Contentful或WordPress和REST API这样的无头CMS) 中提取数据。
  • 超越静态站点: 无任何限制的静态网站的好处。

安装:

npm i gatsby-image

示例代码:

import React from "react"
import { graphql } from "gatsby"
import Img from "gatsby-image"

export default ({ data }) => (
  <div>
    <h1>Hello gatsby-image</h1>
    <Img fixed={data.file.childImageSharp.fixed} />
  </div>
)

export const query = graphql`
  query {
    file(relativePath: { eq: "blog/avatars/kyle-mathews.jpeg" }) {
      childImageSharp {
        # Specify the image processing specifications right in the query.
        # Makes it trivial to update as your page's design changes.
        fixed(width: 125, height: 125) {
          ...GatsbyImageSharpFixed
        }
      }
    }
  }
`

6. react-helmet

可重用的 React 组件将管理您对文档头的所有更改。

采用纯HTML标签并输出纯HTML标签,非常简单,对 React 支持得很好。

特性

  • 支持所有有效标签: title, base, meta, link, 等。
  • 支持服务器端渲染。
  • 嵌套组件覆盖重复的head更改。

安装:

npm i react-helmet

示例代码:

import React from "react";
import {Helmet} from "react-helmet";
 
class Application extends React.Component {
  render () {
    return (
        <div className="application">
            <Helmet>
                <meta charSet="utf-8" />
                <title>My Title</title>
                <link rel="canonical" href="http://mysite.com/example" />
            </Helmet>
            ...
        </div>
    );
  }
};

7. react-virtualized

2021 年你应该尝试的 8 个 React 库插图5

这提供了一个 React 组件来有效地呈现大列表和表格数据,由5个主要组件组成**(Grid, List, Table, Masonry, Collection)**

突出的功能

  • 由于限制了要渲染的调用次数,因此提高了性能。
  • 提供很多 HOC 组件,例如 (AutoSizer, MultiGrid, etc)

安装:

npm i react-virtualized

示例代码:

import React from 'react';
import ReactDOM from 'react-dom';
import {Column, Table} from 'react-virtualized';
import 'react-virtualized/styles.css'; // only needs to be imported once

// Table data as an array of objects
const list = [
  {name: 'Brian Vaughn', description: 'Software engineer'},
  // And so on...
];

// Render your table
ReactDOM.render(
  <Table
    width={300}
    height={300}
    headerHeight={20}
    rowHeight={30}
    rowCount={list.length}
    rowGetter={({index}) => list[index]}>
    <Column label="Name" dataKey="name" width={100} />
    <Column width={200} label="Description" dataKey="description" />
  </Table>,
  document.getElementById('example'),
);

8. react-threesixty

使用 React 360有助于创造迷人的360虚拟现实体验,该体验延伸到台式机、手机和虚拟现实设备。

突出的功能

  • 简化了复杂360和VR用户界面的创建。

安装:

npm i react-threesixty

示例代码:

<ThreeSixtyViewer
  image: 'images/example.jpg'
  count: 19
  perRow: 4
/>

转自:求知编程

切换注册

登录

忘记密码 ?

切换登录

注册

我们将发送一封验证邮件至你的邮箱, 请正确填写以完成账号注册和激活