React.js和Vue.js都是很好的框架。而且Next.js和Nuxt.js甚至将它们带入了一个新的高度,这有助于我们以更少的配置和更好的可维护性来创建应用程序。但是,如果你必须经常在框架之间切换,在深入探讨另一个框架之后,你可能会轻易忘记另一个框架中的语法。在本文中,我总结了这些框架的基本语法和方案,然后并排列出。我希望这可以帮助我们尽快掌握语法,不过限于篇幅,这篇文章只比较React.js和Vue.js,下一篇再谈Next.js个Nuxt.js。
Github: https://github.com/oahehc/rea...
Render
React.js
ReactDOM.render( , document.getElementById("root"));
Vue.js
new Vue({
render: (h) => h(App),
}).$mount("#root");
基本组件
React.js
Class component
class MyReactComponent extends React.Component {
render() {
return Hello world
;
}
}
Function component
function MyReactComponent() {
return Hello world
;
}
Vue.js
Hello World
Prop
React.js
function MyReactComponent(props) {
const { name, mark } = props;
return Hello {name}{mark}
;
}
MyReactComponent.propTypes = {
name: PropTypes.string.isRequired,
mark: PropTypes.string,
}
MyReactComponent.defaultProps = {
mark: '!',
}
...
Vue.js
Hello {{ name }}
...
事件绑定
React.js
Class component
class MyReactComponent extends React.Component {
save = () => {
console.log("save");
};
render() {
return ;
}
}
Function component
function MyReactComponent() {
const save = () => {
console.log("save");
};
return ;
}
Vue.js
自定义事件
React.js
function MyItem({ item, handleDelete }) {
return ;
/*
* 应用useCallback钩子来防止在每次渲染时生成新的函数。
*
* const handleClick = useCallback(() => handleDelete(item), [item, handleDelete]);
*
* return ;
*/
}
...
function App() {
const handleDelete = () => { ... }
return
}
Vue.js
...
State
React.js
Class component
class MyReactComponent extends React.Component {
state = {
name: 'world,
}
render() {
return Hello { this.state.name }
;
}
}
Function component
function MyReactComponent() {
const [name, setName] = useState("world");
return Hello {name}
;
}
Vue.js
Hello {{ name }}
Change-State
React.js
Class component
class MyReactComponent extends React.Component {
state = {
count: 0,
};
increaseCount = () => {
this.setState({ count: this.state.count + 1 });
// 在更新之前获取当前状态,以确保我们没有使用陈旧的值
// this.setState(currentState => ({ count: currentState.count + 1 }));
};
render() {
return (
{this.state.count}
);
}
}
Function component
function MyReactComponent() {
const [count, setCount] = useState(0);
const increaseCount = () => {
setCount(count + 1);
// setCount(currentCount => currentCount + 1);
};
return (
{count}
);
}
Vue.js
{{count}}
双向绑定 (仅Vue.js)
React.js
React没有双向绑定,因此我们需要自己处理数据流
function MyReactComponent() {
const [content, setContent] = useState("");
return (
setContent(e.target.value)}
/>
);
}
Vue.js
计算属性
React.js
React.js没有计算属性,但我们可以通过react hook轻松实现
function DisplayName({ firstName, lastName }) {
const displayName = useMemo(() => {
return `${firstName} ${lastName}`;
}, [firstName, lastName]);
return {displayName};
}
...
Vue.js
{{displayName}}
...
Watch
React.js
React.js没有 watch
属性,但是我们可以通过react hook轻松实现
function MyReactComponent() {
const [count, setCount] = useState(0);
const increaseCount = () => {
setCount((currentCount) => currentCount + 1);
};
useEffect(() => {
localStorage.setItem("my_count", newCount);
}, [count]);
return (
{count}
);
}
Vue.js
{{count}}
Children-and-Slot
React.js
function MyReactComponent({ children }) {
return {children};
}
...
Hello World
Vue.js
...
Hello World
渲染HTML
React.js
function MyReactComponent() {
return ..." }} />;
}
Vue.js
条件渲染
React.js
function MyReactComponent() {
const [isLoading, setLoading] = useState(true);
return (
{isLoading && Loading...}
{isLoading ? is loading : is loaded}
);
}
Vue.js
Loading...
is loading
is loaded
列表渲染
React.js
function MyReactComponent({ items }) {
return (
{items.map((item) => (
-
{item.name}: {item.desc}
))}
);
}
Vue.js
-
{{item.name}}: {{item.desc}}
Render-Props
React.js
function Modal({children, isOpen}) {
const [isModalOpen, toggleModalOpen] = useState(isOpen);
return (
{type children === 'function' ? children(toggleModalOpen) : children}
)
;
}
Modal.propTypes = {
isOpen: PropTypes.bool,
children: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
}
Modal.defaultProps = {
isOpen: false,
}
...
{(toggleModalOpen) => {
...
}}
Vue.js(slot)
...
...
生命周期
React.js
Class component
class MyReactComponent extends React.Component {
static getDerivedStateFromProps(props, state) {}
componentDidMount() {}
shouldComponentUpdate(nextProps, nextState) {}
getSnapshotBeforeUpdate(prevProps, prevState) {}
componentDidUpdate(prevProps, prevState) {}
componentWillUnmount() {}
render() {
return Hello World;
}
}
Function component
function MyReactComponent() {
// componentDidMount
useEffect(() => {}, []);
// componentDidUpdate + componentDidMount
useEffect(() => {});
// componentWillUnmount
useEffect(() => {
return () => {...}
}, []);
// 在渲染之后但在屏幕更新之前同步运行
useLayoutEffect(() => {}, []);
return Hello World;
}
Vue.js
Hello World
错误处理
React.js
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
// 更新状态,这样下一个渲染将显示回退UI。
return { hasError: true };
}
componentDidCatch(error, errorInfo) {}
render() {
if (this.state.hasError) return Something went wrong.
;
return this.props.children;
}
}
...
Vue.js
const vm = new Vue({
data: {
error: "",
},
errorCaptured: function(err, component, details) {
error = err.toString();
}
}
Ref
React.js
Class component
class AutofocusInput extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
}
state = {
content: "",
};
componentDidMount() {
this.ref.current.focus();
}
setContent = (e) => {
this.setState({ content: e.target.value });
};
render() {
return (
);
}
}
Function component
function AutofocusInput() {
const [content, setContent] = useState("");
const ref = useRef(null);
useEffect(() => {
if (ref && ref.current) {
ref.current.focus();
}
}, []);
return (
setContent(e.target.value)}
/>
);
}
Vue.js
性能优化
React.js
PureComponent
class MyReactComponent extends React.PureComponent {
...
}
shouldComponentUpdate
class MyReactComponent extends React.Component {
shouldComponentUpdate(nextProps) {...}
...
}
React.memo
export default React.memo(
MyReactComponent,
(prevProps, nextProps) => {
...
}
);
useMemo
export default function MyReactComponent() {
return React.useMemo(() => {
return ...;
}, []);
}
useCallback
function MyItem({ item, handleDelete }) {
const handleClick = useCallback(() => handleDelete(item), [
item,
handleDelete,
]);
return ;
}
Vue.js
v:once
This will never change: {{msg}}
函数式组件:我们可以将组件标记为 functional
,这意味它无状态 (没有响应式数据),也没有实例 (没有 this
上下文)。
Hello {{ name }}
keep-alive 组件
文章首发《前端外文精选》微信公众号
如果对你有所启发和帮助,可以点个关注、收藏、转发,也可以留言讨论,这是对作者的最大鼓励。
作者简介:Web前端工程师,全栈开发工程师、持续学习者。
继续阅读其他高赞文章
- 2020年的12个Vue.js开发技巧和窍门
- 【小技巧】CSS如何实现文字两端对齐效果?
- 7个简单但棘手的JavaScript面试问题
- 让你可以在2020年成为前端大师的9个项目
- 【实战】Vue.js 图标选择组件开发
- 你必须知道的HTTP基本概念
- 【笔记】Web全栈工程师的自我修养(上)
- 【笔记】Web全栈工程师的自我修养(下)
- 【小技巧】H5页面上如何禁止手机虚拟键盘弹出?
- 拒绝JavaScript,这三个CSS技巧你一定用的上
- 7个能提高你生产力的隐藏Chrome DevTools功能
- 【图文教程】同步你的VSCode设置及扩展插件,换机不用愁