前端框架-React基础

1.虚拟DOM

虚拟DOM本质是一个Object类型的对象

//1.创建虚拟DOM,使用JSX语法,babel会翻译为原生js
const VDOM = (
	<h1 id="title">
    	<span>Hello, React</span>
    </h1>
)
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM, document.getElementById("test"))

jsx语法

1.定义虚拟DOM时,文本字符串不需要写引号
2.引用js定义的变量,要使用 {} ,如:<span>{myData}</span>
3.样式的引入,属性名不是class,而是className
4.在标签中直接定义样式,需要用{{}},如:<span style={{color:'white', fontSize:'29px'}}>{myData}</span>
5.引入react组件时,使用组件名作为标签名,首字母要大写,如:<Mycomponent>
2.遍历数据
const data = ['Angular', 'React', 'Vue']
const VDOM = (
	<div>
		<h1>前端框架列表</h1>
        <ul>{
                data.map((item, index) => { //千万不要用index作为节点的key,这里只是为了方便
                    return <li key={index}>{item}</li> //取遍历数据的节点必须设置key属性
                })
            }</ul>
    </div>
)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-csxwrAmh-1617067323356)(C:\Users\Homelander\OneDrive\学习笔记\笔记中的图片\image-20210310163426177.png)]

3.两种组件
//1.创建函数式组件,函数返回一个虚拟DOM
function Demo() {
    return <h2>这是一个Demo组件</h2>
}
//2.渲染组件到面页
ReactDOM.render(<Demo/>, document.getElementById('test'))
//1.创建类式组件,类中的render函数返回一个虚拟DOM
class Demo extends React.Component {
	render() {
        return <h2>我是一个Demo组件</h2>
    }
}
//2.渲染组件到面页
ReactDOM.render(<Demo/>, document.getElementById('test'))
/*
	ReactDOM渲染组件时发现该组件是类定义的,会自动new出此类的实例,并调用该实例对象中的render方法
*/
4.事件,this指向问题

详见:https://www.jianshu.com/p/c1ee12a328d2

//原生绑定事件的三种方式
<body>
	<button id="btn1">按钮1</button>
    <button id="btn2">按钮2</button>
    <button οnclick="demo()">按钮3</button>
    
    <script>
        方式1:不建议使用
    	const btn1 = document.getElementById('btn1')
        btn1.addEventListener('click', () => {
            alert('按钮1被点击了')
        })
        
        方式2:不建议使用
        const btn2 = document.getElementById('btn2')
        btn2.onclick = () => {
            alert('按钮2被点击了')
        }
        
        方式3:更推荐的写法
        function demo() {
            alert('按钮3被点击了')
        }
    </script>
</body>

//react绑定事件的方法
<script>
	class Weather extends React.Component {
        /*在react中,构造器仅用于以下两种情况:
		  1.通过this.state赋值对象来初始化内部state
          2.为事件处理函数绑定实例
          如果不存在以上两种情况的使用,可以不写构造器
        */
        constructor(props) {
            super(props) //必须调用super
            this.state = {isHot:false}
            this.demo = this.demo.bind(this) //重点,这行代码就将demo方法绑定到了当前对象实例上
        }
        render() {
            const {isHot} = this.state
            return <h1 onClick={this.demo}>今天天气很{isHot ? '热' : '冷'}</h1>
        }
        
        //demo方法放在了类的proto对象中,以供当前实例对象使用
        demo() {
        	console.log('标题被点击了')
            console.log(this) //注意:只有在当前类的实例对象调用demo方法,this才能指向当前对象
            //如果绕过实例,直接调用demo方法,this将指向window实例
            //如果方法开启了'use strict'模式,this将为undefined,而react类中定义的方法会默认开启use strict
            //详见 https://www.bilibili.com/video/BV1wy4y1D7JT?p=15
            //这里想要让this指向当前类对象实例,需要在构造器中添加this.demo = this.demo.bind(this)
            //当在箭头函数中使用this时,箭头函数会使用其外层的this作为自己的this
    	}
    }
    
    ReactDOM.render(<Weather/>, document.getElementById('test'))
</script>
5.数据绑定

react、vue都是单向数据流的框架,即数据的流向只能通过props由外层到内层 一层一层往里传递

vue可以通过v-modle实现双向绑定,使view层和model层的映射关系实时更新

react是单向数据绑定,view层的修改需要使用react内置的api方法,setState

demo() {
    const isHot = this.state.isHot
    //只有setState,数据的变化才能在面页上更新,setState只会更新state中指定属性的值,不影响其他属性
    this.setState({isHot: !isHot}) 
    
}
6.精简初始化代码
//开发时的写法
//react中的类,可以直接以赋值语句的形式定义属性,new实例时会自动初始化类内部的所有属性
class Weather extends React.Component {
    state = {
        isHot: false,
        wind: '大风'
    }
	render() {
        const {isHot, wind} = this.state
        return (
            <h1 onClick={this.demo}>今天天气很{isHot ? '热' : '冷'},{wind}</h1>
        )
    }
	//将demo方法定义为属性,这里必须使用箭头函数,this的才能正确指向当前类的实例
	demo = () => {
        const isHot = this.state.isHot
        this.setState({
            isHot: !isHot
        })
    }
}
7.组件标签属性的指定
class Person extends React.Component {
    render() {
        const {name, age, sex} = this.props //props属性是只读的,只能读取属性值,不能写入属性值
        return (
            <ul>
            	<li>姓名:{name}</li>
                <li>年龄:{age}</li>
                <li>性别:{sex}</li>
            </ul>
        )
    }
    //对组件标签属性类型进行限制
    static propTypes = {  //注意,必须使用static修饰,表示给类添加属性,而非给实例对象添加属性
        name: PropTypes.string.isRequired,
        sex: PropTypes.string,
        age: PropTypes.number
    }
    //给组件标签属性指定默认值
    static defaultProps = {
        sex: '跨性别者',
        age: 18
    }
}

//渲染组件到面页
ReactDOM.render(<Person name="小红" age={19} />, document.getElementById('test1'))
ReactDOM.render(<Person name="小蓝" sex="男"/>, document.getElementById('test2'))
const p = {name: '小白', age: 20, sex: '女'}
ReactDOM.render(<Person {...p}/>, document.getElementById('test2'))
8.ref的使用

ref是React提供的用来操纵React组件实例或者DOM元素的接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NJTy6Zm2-1617067323359)(C:\Users\Homelander\OneDrive\学习笔记\笔记中的图片\image-20210310120247211.png)]

上面的ref回调函数写法也可以写成内联形式的,效果一样,如下,开发时写下面这种能简洁点,就不用再多定义一个函数

render() {
    return (
    	<div>
            {<!-- 这样在函数中就可以使用this.textInput直接操作input节点 -->}
        	<input type="text" ref={(element) => {this.textInput = element;}}></input>
        </div>
    )
}
9.受控组件和非受控组件

非受控组件

class Login extends React.Component {
    handlerSubmit = (event) => {
        event.preventDefault() //阻止表单提交
        const {username, password} = this
        alert(`用户名:${username.value},密码:${password.value}`)
    }
    render() {
        return(
        	<form onSubmit={this.handleSubmit}>
            	用户名:<input type="text" name="username" ref={(ele) => {this.username = ele;}}></input>
                密码:<input type="password" name="password" ref={(ele) => {this.password = ele;}}></input>
                <button>登录</button>
            </form>
        )
    }
	ReactDOM.render(<Login/>, document.getElementById('test'))
}

受控组件(类似vue中的双向数据绑定,更建议使用这种写法)

class Login extends React.Component {
    //初始化状态
    state = {
        username: '',
        password: ''
    }
	//保存表单数据到状态中
	/*
		高阶函数:符合以下两条中的任意一条,就是高阶函数
		1.一个函数接收的参数也是一个函数
		2.一个函数返回值也是一个函数
		常见的如:Promise、setTimeout、arr.map()等等
		
		函数的柯里化:通过函数调用返回函数,经过多次参数传递最后统一处理返回结果的函数编写方式
		简单来说,就是调用函数时,如果函数后加了小括号(一般是因为要传递参数),就要柯里化,如: onClick={this.doClick(p)}
		如果函数不需要传递参数,那么可以不加小括号调用,就不用柯里化,如: onClick={this.doClick}
	*/
	saveFormData = (param, event) => {
        return (event) => {
            this.setState({[param]: event.target.value})
        }
    }
    //表单提交的回调函数
    handleSubmit = (event) => {
        event.preventDefault() //阻止表单提交
    }
    render() {
        return(
        	<form onSubmit={this.handleSubmit}>
            	用户名:<input type="text" name="username" onChange={this.saveFormData('username')}></input>
                密码:<input type="password" name="password" onChange={this.savePassword('password')}></input>
                <button>登录</button>
            </form>
        )
    }
	ReactDOM.render(<Login/>, document.getElementById('test'))
}

为了避免函数柯里化,开发时常用的写法

class Login extends React.Component {
    //初始化状态
    state = {
        username: '',
        password: ''
    }
	//保存表单数据到状态中
	saveFormData = (param, event) => {
        this.setState({[param]: event.target.value}) 
    }
    //表单提交的回调函数
    handleSubmit = (event) => {
        event.preventDefault() //阻止表单提交
    }
    render() {
        return(
        	<form onSubmit={this.handleSubmit}>
            	用户名:<input type="text" name="username" 
                        onChange={(event) => {this.saveFormData('username', event)}></input>
                密码:<input type="password" name="password" 
                        onChange={(event) => {this.savePassword('password', event)}></input>
                <button>登录</button>
            </form>
        )
    }
	ReactDOM.render(<Login/>, document.getElementById('test'))
}
10.react的生命周期

实际开发中最重要的且最常用的就三个钩子函数

  • render:初始化渲染或更新渲染时调用
  • componentDidMount:开启监听,发送ajax请求
  • componentWillUnmount:清理定时器
/*
    钩子函数
    1.初始化阶段:由ReactDOM.render()触发
    	constructor() → componentWillMount() → render() → componentDidMount()
    2.更新阶段:由组件内部this.setState()或父组件render触发
    	shouldComponentUpdate() → componentWillUpdate() → render() → componentDidUpdate()
    3.卸载阶段:由ReactDOM.unmountComponentAtNode()触发
    	componentWillUnmount()
*/

//组件挂载前执行一次
componentWillMount() { //不常用,即将弃用
}

//父组件render后执行一次
componentWillReceiveProps() { //不常用,即将弃用
}

//setState()完成后,执行该函数,返回布尔值,不写该函数,react会默认执行并返回true
shouldComponentUpdate() {
}

//shouldComponentUpdate()或forceUpate()完成后,执行该函数,forceUpate可以使不改变状态的情况下调用该函数
componentWillUpdate() { //不常用,即将弃用
}

//渲染(挂载)组件
render() { //必须使用
}

//组件挂载完毕后执行,且只执行一次,类似于vue的mounted
componentDidMount() { //常用,一般在其中做一些初始化的工作,如开启定时器、发送网络请求、订阅消息
}

//组件如果被卸载,则在卸载前执行一次
componentWillUnmount() { //常用,一般在其中做一些收尾的工作,如关闭定时器、取消订阅消息
}
11.父子通信

父传子,使用props

//1.父组件中,render函数里用标签引入它的子组件,在标签中可以定义属性参数,实现父组件传递子组件
class Father extends React.Component {
    state = {
        data: {name, age, gender}
    }
    render() {
        return <Child data={this.state.data}>  {/*将父组件中的data属性传给子组件*/}
    }
}
//2.子组件中,使用props接收来自父组件的属性参数
class Child extends React.Component {
    const {data} = this.props
    render() {
        return <button>{data.name}</button>
    }
}

子传父,使用函数

//1.父组件中,render函数里的标签传入一个函数,函数的参数即为需要传递的属性
class Father extends React.Component {
    state = {
        data: {name, age, gender}
    }
	//该函数被传递给子组件,子组件通过调用函数,传递参数param给父组件
	changeData = (param) => {
        //处理子组件传递过来的参数,最后更新状态
        this.name = param.name
    }
    render() {
        return <Child changeData={this.changeData}>  {/*将父组件中的函数传给子组件*/}
    }
}
//2.子组件中,使用props接收来自父组件的函数
class Child extends React.Component {
    
    change = () => {
        axios.get(`/api/change/name`).then(response => {
            this.props.changeData(response.data.name)
        })
    }
    
    render() {
        return <button onClick={this.change}></button>
    }
}
12.代理

为了解决跨域问题,项目可能会设置有代理的服务器,负责转发请求

在src路径下创建setupProxy.js文件

//先安装 npm install http-proxy-middleware --save
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  //参数 /api 表示请求url中必须包含 /api 才能被拦截到并触发代理
  app.use(createProxyMiddleware('/api', {
      //代理服务器1的地址
      target: 'http://121.36.69.149:8033', 
      //控制后端收到的请求头中Host的值,一般设置为true,这样后端得到的是代理服务器的地址而非真实请求源地址,默认为flase
      changeOrigin: true,
      //请求发送到后端,把后端接收到的url中的 /api 去掉,如果不设置此属性,后端@RequestMapping就需要把 /api 加上
      pathRewrite: {'^/api': ''},
      //如果是https接口,这个参数需要设置为true
      secure: false
  }));
  //代理服务器2
  app.use(createProxyMiddleware('/api2', {
      //代理服务器2的地址
      target: 'http://121.36.69.149:8034', 
      changeOrigin: true,
      pathRewrite: {'^/api2': ''},
      secure: false
  }));
};
13.消息订阅与发布

为了避免组件之间传递数据的繁琐性操作,引入消息中间件 PubSubJS,极大的简化任意组件之间的通信

https://www.npmjs.com/package/pubsub-js

发布消息的组件

import PubSub from 'pubsub-js'

export default class Pub extends Component {
    change = () => {
        //发送请求前先发布消息,修改订阅消息组件state中的某些需要改变状态的属性
        PubSub.publish('msgname', {
            isLoading: true
        })
        axios.get(`api/change/name`).then(response => {
            //请求收到响应数据后,使用消息发布修改订阅消息组件的state
            PubSub.publish('msgname', {
                name: response.data.name
                age: response.data.age
                isLoading: false
            })
        })
    }
}

订阅消息的组件

import PubSub from 'pubsub-js'

export default class Sub extends Component {
    
    state = {
        name: '',
        age: 0,
        isLoading: false
    }

	componentDidMount() {
        this.token = PubSub.subscribe('msgname', (msg, data) => {
            this.setState(data) //从消息发布组件处获取最新的state数据,更新state
        })
    }

	componentWillUnmount() {
        PubSub.unsubscribe(this.token) //组件卸载前,取消订阅消息
    }

	render() {
        return (
        	<div>
                
            </div>
        )
    }
}
14.请求
  • fetch https://github.com/camsong/blog/issues/2
fetch(`/api/change/name`).then(response => { //第一个response仅能获取到连接是否成功,拿不到数据
    console.log('连接服务器成功');
    return response.json() //第一个response的json方法可以继续返回一个Promise对象,该对象里包含了数据
}).then(response => {
    console.log('获取数据', response) //从第二个response中就可以直接获取到数据
}).catch(error => {
    console.log('请求错误', error.message)
})

//优化上面的代码
try {
    const response = await fetch(`/api/change/name`)
    const data = await response.json()
    console.log('获取数据', data)
} catch(error) {
    console.log('请求错误', error.message)
}
  • axios
//略
15.路由

前端路由本质是靠操作window.history实现的,原理代码如下

<body>
    <a href="http://www.atguigu.com" onclick="return push('/test1') ">push test1</a><br><br>
    <button onClick="push('/test2')">push test2</button><br><br>
    <button onClick="replace('/test3')">replace test3</button><br><br>
    <button onClick="back()">&lt;= 回退</button>
    <button onClick="forword()">前进 =&gt;</button>
    <script type="text/javascript" src="https://cdn.bootcss.com/history/4.7.2/history.js"></script>
    <script type="text/javascript">
        // let history = History.createBrowserHistory() //方法一,直接使用H5推出的history身上的API
        let history = History.createHashHistory() //方法二,hash值(锚点)后边都带一个#,兼容性极好

        function push (path) {//入栈,浏览器路由跳转后默认执行的方法
            history.push(path)
            return false//改变浏览器的历史记录,但是不会进行跳转
        }

        function replace (path) {//替换栈顶记录,如果想禁用浏览器前进后退,就给顶层路由标签设置 replace={true}
            history.replace(path)
        }

        function back() {//回退,出栈
            history.goBack()
        }

        function forword() {//前进
            history.goForward()
        }

        history.listen((location) => {//做监听,只要路径发生变化就执行
            console.log('请求路由路径变化了', location)
        })
    </script>
</body>
</html>

react router针对web开发提供了react-router-dom

import { HashRouter, Route, Switch } from 'react-router-dom';

function App() {
  return (
      {/* 必须在外侧指定HashRouter或BrowserRouter标签 */}
      <HashRouter>
          {/* 使用Switch标签,如果存在相同path对应多个component,也只会匹配第1个 */}
          <Switch>
              {/* 注册路由,匹配路径展示路由,如果添加 exact={true} 则可以精准匹配路径,慎用 */}
              <Route path="/" component={MainRoutes} />    
          </Switch>
      </HashRouter>
  );
}

路由组件和普通组件区别

  • 路由组件放在pages文件夹中,普通组件放在components文件夹中
    • 普通组件:<Login/>
    • 路由组件:<Route path="/login" component={Login}/>
  • 路由组件接收到的props包含了history、location、match三个对象,普通组件接收到的props属性只有父组件传递的值
    • 通过 withRouter 可以使普通组件也拥有路由组件的这些属性
history:
	go: f go(n) 	//n表示前进或后退步长
	goBack: f goBack()
	goForward: f goForward()
	push: f push(path, state)
	replace: f replace(path, state)
location:
	pathname: "/login"
	search: ""
	state: undefined
match:
	params: {}    	//从这里可以获取路由path匹配时传递的参数,如id,通过 this.props.match.params 获取
	path: "/login"
	url: "/login"

withRouter的使用

import {withRouter} from 'react-router-dom'

class Nomal extends Component {...}

export default withRouter(Header)

重定向:当遇到所有注册路由都无法匹配的路径,一般都设置重定向,卸载所有路由的最下方

import { Redirect, Switch, Route } from 'react-router-dom';

  render() {
    const redirectData = this.getRedirectData();
    return (
      <Switch>
        {/* 渲染权限路由表 */}
        {routerData.map(this.renderNormalRoute)}

        {/* 路由重定向,嵌套路由默认重定向到当前菜单的第一个路由 */}
        {redirectData.map((item, index) => {
          return <Redirect key={index} exact from={item.from} to={item.to} />;
        })}
            
        {/* 首页默认重定向到 /login */}
        <Redirect exact from="/" to="/login" />

        {/* 未匹配到的路由重定向到 404 */}
        <Route component={NotFound} />
      </Switch>
    );
  }
}

路由传递参数

  • params参数:能在地址栏显示参数
//向路由组件传递params参数
<Link to={`/user/${userData.id}`}>{userDada.username}</Link>

//路由中声明接收params参数
	{
		name: '用户信息',
		path: '/user/:id',
		layout: 'mainLayout',
		component: UserInfo,
	},

//组件中获取params参数
const { id } = this.props.params
  • search参数:需要借助querystring解析
//向路由组件传递search参数
<Link to={`/user/?id=${userData.id}&username=${userDada.username}`}>{userDada.username}</Link>

//路由中声明接收search参数,正常写path,无需修改
	{
		name: '用户信息',
		path: '/user',
		layout: 'mainLayout',
		component: UserInfo,
	},

//组件获取search参数,首先 import qs from 'querystring'
const {search} = this.props.location
const {id, username} = qs.parse(search.slice(1))  
  • state参数:地址栏不显示参数,刷新地址,使用HashRouter会丢失参数,使用BrowserRouter不会丢失参数
//向路由组件传递state参数
<Link to={{
        path: '/user',
        state: {
            id: userData.id,
            username: userData.username
        }
    }}>{userDada.username}</Link>

//路由中声明接收state参数,正常写path,无需修改
	{
		name: '用户信息',
		path: '/user',
		layout: 'mainLayout',
		component: UserInfo,
	},

//组件获取state参数
const {id, username} = this.props.location.state

编程式路由跳转

	pushRoute = (id, username) => {
        this.props.history.push(`/user/${id}`)
    }

	<button onClick={() => this.pushRoute(userData.id, userData.username)}>手动push到新路由</button>
16.UI库

React国内常用ant-design作为UI库,由蚂蚁金服发布 https://ant.design/docs/react/introduce-cn

自定义主体颜色和按需引入样式的方法参考官方文档,或直接修改webpack配置文件,具体方法自行百度

17.Redux

在这里插入图片描述

  • Store:存储数据的容器,全局一个
import { createStore } from 'redux';

//创建store
const store = createStore(fn);
//createStore可以传入3个参数
const store = createStore(
  reducer, //参数1:所有的reducer集合
  initial_state, //参数2(非必需):自定义state的初始状态
  applyMiddleware(thunk, promise, logger) //参数3(非必需):中间件,如果不传initial_state,那么中间件就是第2个参数
);

//某一时间点中store存储的数据集合称为state,获取state
const state = store.getState();

//store可以监听state的变化
let unsubscribe = store.subscribe(listener); //一旦state发送变化就执行listener函数
unsubscribe(); //执行监听的返回结果函数就可以取消监听
  • Action:组件中通过 store.dispatch(action) 通知Store
//Action对象包含 type 和 payload 两个属性
const action = {
    type: 'actionname', //表示Action的名称,必需
    payload: {}	//表示Action携带的信息,非必需
}

//通过函数来返回action,这样的函数被称为 Action Creator
const addTodo = (data) => {
    type: 'actionname'
    data
}
const action = addTodo("LearnRedux")
//项目中,通常把一个面页中使用到的所有action函数都封装到一个actionCreator.js文件
  • Reducer:Store接收到Action后通过Reducer修改state为新值并返回给Store
//reducer是函数,接收 旧的state 和 action 作为参数,返回 新state
const reducer = (state, action) => {
    ...
    return newState;
}
//reducer函数不需要手动调用,而是由store.dispatch自动触发,每当store接收到action都会自动执行reducer
//要让store控制reducer,就需要在createStore时传入reducer
const store = createStore(reducer)

reducers的拆分

//Redux提供了一个 combineReducers 方法,用于Reducer的拆分
import { combineReducers } from 'redux';

const reducer = combineReducers({
  //key为子组件名,value为对应reducer
  chatLog: chatLogReducer	//reducer 1
  statusMessage: statusMessageReducer //reducer 2
  userName: userNameReducer //reducer 3
  ...
})

export default reducer;
18.Redux中间件

详细教程参考:http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html

中间件是一个函数,原理是对store.dispatch方法进行改造,在 发出Action 和 执行Reducer 这两步之间,添加了其他功能

如何使用中间件:Redux提供了 applyMiddleware 函数

import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import reducers from './reducers'

const store = createStore(
    //封装的reducer函数集合
    reducers, 
    //组合redux-thunk中间件和Redux DevTools浏览器插件
    compose(applyMiddleware(thunk), 
            window.__REDUX_DEVTOOLS_EXTENSION__ ?window.__REDUX_DEVTOOLS_EXTENSION__() : f => f)
)

export default store;

redux-thunk

//redux-thunk可以改造store.dispatch(),使其可以接受函数作为参数,而默认只能接受对象作为参数

connect()

connect方法包装组件,使 组件 和 Store 连接起来

import { connect } from 'react-redux'

export default connect(
  mapStateToProps, //映射state到props,返回一个对象,里面每一个键值对都是一个映射
  mapDispatchToProps //映射action到props,返回一个对象
)(TodoList);
//mapStateToProps函数接收state作为参数,每当state更新的时候,就会自动执行
const mapStateToProps = (state) => {
  return {
    contact: state.getIn(['contact', 'contact']).toJS(),
  };
};
//mapDispatchToProps函数接收dispatch作为参数
const mapDispatchToProps = (dispatch) => ({
  getContact(keyword) {
    dispatch(actionCreators.getContactOperation(keyword));
  },
  getContactDetail(id) {
    dispatch(actionCreators.getContactDetailOperation(id));
  },
  deleteContact(id, value) {
    dispatch(actionCreators.deleteContactOperation(id, value));
  },
});
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue-React组件库的实现原理主要是通过将Vue组件转化为React组件,或将React组件转化为Vue组件,从而实现在Vue和React项目中同时使用的目的。 具体来说,Vue-React组件库的实现原理有以下几种方式: 1. 使用Vue-React转换器:Vue-React转换器是一个将Vue组件转换为React组件的工具,可以实现在React项目中使用Vue组件。转换器的实现原理是将Vue组件的模板转换为React组件的JSX语法,再在React项目中引入转换后的React组件。这种方式需要注意Vue组件的语法和React组件的语法差异,以及转换器的兼容性和性能问题。 2. 使用Vue-React组件库:Vue-React组件库是一个同时支持Vue和React的UI组件库,可以直接在Vue和React项目中使用。组件库的实现原理是针对Vue和React两种框架分别提供了组件的实现,通过封装和兼容处理,实现在两种框架中的使用。这种方式需要注意组件的兼容性和性能问题,以及组件库的选择和使用方法。 3. 使用Web Components:Web Components是一种通用的组件规范,可以在各种前端框架中使用。Vue和React都支持Web Components规范,因此可以使用Web Components实现在两种框架中共享组件。这种方式需要注意组件的规范和兼容性问题,以及Web Components的使用方法和浏览器支持情况。 需要注意的是,使用Vue-React组件库的方式相对简单,而且在实现原理上比较清晰,因此在实际开发中比较常用。但是,不同的Vue-React组件库实现方式略有不同,需要根据具体组件库的文档进行使用和配置。同时,也需要注意不同框架之间的差异和兼容性问题,避免出现不可预期的错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值