Google前端工程师尤雨溪于2014年创建了这个框架,Vue是一套用于构建用户界面的渐进式框架,与其他大型框架不同的是,Vue被设计为可以自底向上逐层应用,Vue核心时只关注视图层,不仅易于上手,还便于与第三方库或既有的项目整合
与Vue不同,react库是由FaceBook创建的,最初是为了FackBook广告流量管理创建的,那是FackBook遇到了维护和编码方面的问题,它以动态创建和交互UI的能力而闻名
vue和react都是推崇组件式的开发理念,但是在设计的核心思想上有很大的差别
Vue的整理思想仍然是拥抱经典的html(结构)+css(表现)+jd(行为)的形式,Vur鼓励开发者使用template模板,并提供指令供开发着使用(v-if、v-show、v-for等等),因此开发vue应用又是会有一种在写经典web应用(结构、表现、行为分离)的感觉。另一方面,在针对组件数据上,Vue2.0通过Object.defineProperty对数据做到了更细致的监听,景区实现组件级别的更新。
react整体上是函数式的思想,组件使用jsx语法,all in js,将html与css全部融入javaScript,jsx语法相对来说更加灵活,刚开始从Vue转React的时候我也不是很适应,觉得react的写法很自由。当组件调用setState或props变化的时候,组件内部render会重新渲染,子组件也会随之重新渲染,可以通过shouldComponentUpdate或者PrueComponent可以避免不必要的重新渲染
vue组件是使用.vue文件来表示,vue组件将html、css、js组合到一起,模板部分使用数据使用{{}},形式如下:
// 模板(html)
{{name}}
// 数据管理(js)
// 样式(css)
组件的使用:
react推荐使用jsx或者js文件来表示组件,react支持class组件和function组件,react中是使用{}包裹变量,且需要注意的是,组件名称必须大写字母开头,React会将以小写字母开头的组件视为原生Dom标签,例如
代表html的div标签,而1)class组件
import React from 'react';
class NewComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'xx'
};
}
render() {
rerurn({name});
}
}
export default NewComponent;
2)function组件
import React, { useState } from 'react';
function NewComponent() {
const [name, setName] = useState('');
return ({name});
}
export default NewComponent;
组件中数据管理通常包含2部分,来自父组件的数据props与自身的数据
vue与react中的props都是单项数据流的,父级prop的更新会向下流动到子组件中,但是反过来不行。props可以是数组或对象,用于接收来自父组件的数据。
Props
静态prop传递布尔值true可以这样写,传值false仍然需要使用动态prop传值
动态赋值使用v-bind,可以简写为:
// 简写形式
动态prop常用来传递对象、数组、布尔值(false值,true值可以直接传属性 )等
data
vue中使用data来管理组件的数据,vue将会递归将data数据转为getter/setter,从而让data的属性能够响应数据变化。对象必须是纯粹的对象(含有零个或多个key/value对)。一旦观察过,不需要再次在数据对象上添加响应式属性。因此推荐在创建实力之前,就声明所有的根级响应式属性。
当一个组件被定义,data必须声明为返回一个初始数据对象的函数
export default {
name: 'NewComponent',
data() {
return {
name: 'xxx',
age: 12
}
}
}
当需要在组件内修改数据时,可以直接通过vue实力来修改:
methods: {
changeName() {
this.name = 'new Name';
}
}
props
react中的props也与vue一样可以传递静态或动态props,静态props一般传递字符串
函数组件和class组件都可以使用props,函数组件使用props参数获取父组件传递的props
1)函数组件获取props
function Welcome(props) {
return Hello, {props.name}
;
}
const element = ;
2)class组件获取props(通过this.props获取)
class Welcome extends React.Component {
constructor(props) {
super(props);
}
render() {
const { name } = this.props;
return {name};
}
}
动态的props
state
react中使用state来管理组件内的数据,hooks的出现使用函数组件也具备管理state的能力
1)class组件中的state
class组件在构造函数(constructor)中定义组件内数据(state),修改数据必须通过setSate修改,不能直接修改state,这点非常重要。
class Welcome extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'xx'
};
this.changeName = this.changeName.bind(this);
}
changeName() {
this.setState({
name: 'new name'
});
}
render() {
const { name } = this.state;
return {name};
}
}
关于class组件的setState有以下需要注意点:
setState更新是异步的,但是在setTimeout和原生时间中式同步的
setState更新式组件部分数据,更新机制式合并数据
当需要使用上一个state值时,可以让setSate()接收一个函数而不是一个对象。这个函数用上一个state作为第一个参数,将此次更新被应用时的props作为第二个参数:
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
2)function组件中的useState(hook)
react16.0之前函数组件知识纯的渲染组件,hooks的出现赋予了函数组件管理state的能力
useState返回一个state,以及更新state的函数,如果新的state需要通过使用先前的state计算得出,那么可以将函数传递给setState。该函数将接收先前的state,并返回一个更新后的值
import React, { useState } from 'react';
function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
>
);
}
关于setState有一下注意点:
组件数据交互指的是父子组件、兄弟组件、跨层组件之间传递数据。兄弟组件之间可以通过事件总线或者通过父组组件传递数据
vue:props+自定义事件
react:props+回调
Vue
vue中父组件通过props传递数据给子组件,子组件使用$emit触发自定义事件,父组件中监听子组件的自定义事件获取子组件传递过来的数据
子组件中使用$emit传递自定义事件myEvent
{{name}}
父组件使用@myEvent监听自定义事件,回调参数是子组件传回的数据:
React
react中父组件使用props传递数据和回到函数给子组件,子组件通过props传下来的回调和桉树返回数据,父组件通过回调函数获取子组件传递上来的数据
子组件通过props接收夫罪案传下来的回调事件:
import React, { useState } from 'react';
function Children(props) {
const { myEvent } = props;
const [name, setName] = useState('xxx');
const changeName = () => {
setName('new name');
myEvent('new name');
};
return {name};
}
父组件通过回到事件获取子组件传递的参数:
function Parent() {
const changeName = name => {
console.log(name);
};
return ;
}
vue和react都支持跨组件传递数据,vue中主要通provide/inject实现,react中主要是通过Context实现
Vue
vue中通过provide/inject在祖先组件向所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效
祖先组件中定义provide选项,provide选项应该是一个对象或者返回一个对象的函数
子组件通过inject选项获取祖先组件provide选项值,inject选项应该是一个字符串数组或者对象
{{message}}
注意:provide和inject绑定并不是可响应式的,这是刻意为之,然而,如果你传入一个可监听的对象,那么其对象的属性还是可响应的。
react
Context提供了一个无需为每层手动添加props,就能在组件树间进行数据传递的方法
import React,{useState} from 'react'
//创建Context对象
const MyContext=React.createContect({theme:'black'})
function Parent(){
const changeName=name=>{
console.log(name);
}
//Context.provider向消费组件传值
return (
)
}
消费组件获取Context的两种方式:
1)class组件通contextType获取最近Context上的那个值
class DeepChildren1 extends React.Component{
constructor(props){
super(props)
}
static contextType=MyContext;
render(){
return (
{this.context.theme}123
)
}
}
2)函数组件通过Context.Consumer订阅到Context的变更
function DeepChildren(props){
return (
{
(value)=> ({value.theme})
}
)
}
关于Context需要注意:
对于css中class与style处理上,vue与react也存在较大差异
vue对class与style特意做了增强,可以传字符串、对象、数组
class
1)给class绑定字符串
2)给class绑定对象
data如下:
data: {
isActive: true,
hasError: false
}
HTML将被渲染成:
3)给class绑定数组
data如下:
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
HTML 将被渲染为:
style
style用来绑定内联样式,支持传对象、数组、使用需要添加浏览器引擎的css属性时,如transform、Vue.js会自动侦测并添加相应的前缀
1)传对象,css属性名可以用驼峰式或者短横线分割
data如下:
data: {
activeColor: 'red',
fontSize: 20
}
HTML将被渲染为:
2)传数组将多个样式应用到同一个元素上:
data如下:
baseStyles: {
fontSize: '20px',
color: 'blue'
},
overridingStyles: {
height: '80px'
}
HTML将被渲染为:
react使用className用于指定css的class,react不能直接为组件指定class
className
react中的饿className一般传值字符串常量或者字符串变量,不能传递数组或者对象语法
1)传递字符串常量
function NewComponent(){
return this is a new Component.
}
2)传递字符串变量
function NewComponent(){
const newClass='container'
return this is a new Component.
}
3)传递多个class,可以使用es6的模板字符串实现
function NewComponent(){
const newClass="container"
return .....
}
4)如果需要传递数组或者对象语法时,可以引入classnames库实现:
import classNames from 'classnnames';
function NewComponent() {
const newClass = 'container';
return This is New Component.;
}
html将被渲染为:
style
通常不推荐将style属性作为设置元素样式的主要方式。在多数情况下,应使用className属性来引用外部css样式表中定义的class。style在react应用中多用于在渲染过程中添加动态计算样式
const divStyle={
color:'blue',
backgroundImage:'url('+imgUrl+')'
}
function HelloWordComponent(){
return Hello World!
}
注意:样式不会自动补齐前缀,如需支持旧版本浏览器,请手动补充对应对的样式属性:
const divStyle = {
WebkitTransition: 'all', // note the capital 'W' here
msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};
function ComponentWithTransition() {
return This should work cross-browser;
}
我们经常说的生命周期无谓就是组件的生命周期,一般包括:初始化,挂在、更新、卸载四个大阶段,接下来分别看看vue和react的生命周期
vue生命周期图示:
react生命周期氛围16.0之前和16.0之后
16.0之前
1)初始化阶段:constructor
是class组件默认的方法,常用来初始化state或者设置属性等
class Counter extends React.component{
construtor(props){
super(props)
this.state={
count:0
}
this.color='red'
}
}
2)挂在阶段
注意:不要在render里面修改state,会引起死循环导致卡死
3)更新阶段:
但通过setState修改state或父组件重新render引起props更新,都会引起子组件的重新render
一般我们通过该钩子来优化性能,避免子组件不必要的渲染
注意:不能在此方法中调用
this.setState
注意:可以在componentDidUpdate()中直接调用setState(),但是它必须被包裹在一个条件语句中,否则会导致死循环
4)卸载阶段
注意:componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。
16.0之后
react16.0之后移除的生命周期函数:
但是为了向下兼容,react并未删除这三个生命周期函数,新增“UNSAFE_”为前缀别名和的三个函数:UNSAFE_componentWillMount()
、UNSAFE_componentWillReceiveProps()
、UNSAFE_componentWillUpdate()
新增的生命周期函数
static getDerivedStateFromProps(nextProps,preState)
getSnapshotBeforUpdate(nextProps,prevState)
react16.0更新之后的生命周期函数总结:
(1)初始化阶段保持不变
(2)挂载阶段:getDerivedStateFromProps=>render=>componentDidMount
(3)更新阶段:getDerivedStateFromProps=>shouldComponentUpdate=>render=>getSnapshotBeforeUpdate=>componentDidUpdate
(4)卸载阶段保持不变
vue和react在事件处理上用法也有所差异
vue中使用的是v-on指令的方式为元素绑定时间,并在出发时运行一些JavaScipt代码,通常使v-on接受一个需要调用的方法名称
1)直接绑定方法,不传递任何参数,回调函数参数是浏览器事件event对象
Greet
method:
methods: {
greet(event) {
console.log(event);
}
}
2)内联调用方法
Greet
methods: {
greet(message) {
this.message = message;
}
}
有时候也需要在method中访问原生DOM事件,可以讲$event显示传入method中
Greet
methods: {
greet(message, event) {
this.message = message;
}
}
3)事件修饰符和按键修饰符
Vue为事件添加了事件修饰和按键修饰符
事件修饰符:
在事件处理程序中调用event.preventDefault()或者event.stopPropagation()是非常常见的需求,为了解决这个问题,Vue为v-on提供了事件修饰符,修饰符是由.开头的指令后缀来表示的。
...
...