内容简介:推荐阅读
React.js和Vue.js都是很好的框架。而且Next.js和Nuxt.js甚至将它们带入了一个新的高度,这有助于我们以更少的配置和更好的可维护性来创建应用程序。但是,如果你必须经常在框架之间切换,在深入探讨另一个框架之后,你可能会轻易忘记另一个框架中的语法。在本文中,我总结了这些框架的基本语法和方案,然后并排列出。我希望这可以帮助我们尽快掌握语法,不过限于篇幅,这篇文章只 比较React.js和Vue.js ,下一篇再谈Next.js个Nuxt.js。
Github
https://github.com/oahehc/react-vue-comparison
Render
React.js
ReactDOM.render(<App />, document.getElementById("root"));
Vue.js
new Vue({
render: (h) => h(App),
}).$mount("#root");
基本组件
React.js
Class component
class MyReactComponent extends React.Component {
render() {
return <h1>Hello world</h1>;
}
}
Function component
function MyReactComponent() {
return <h1>Hello world</h1>;
}
Vue.js
<template>
<h1>Hello World</h1>
</template>
<script>
export default {
name: "MyVueComponent",
};
</script>
Prop
React.js
function MyReactComponent(props) {
const { name, mark } = props;
return <h1>Hello {name}{mark}</h1>;
}
MyReactComponent.propTypes = {
name: PropTypes.string.isRequired,
mark: PropTypes.string,
}
MyReactComponent.defaultProps = {
mark: '!',
}
...
<MyReactComponent name="world">
Vue.js
<template>
<h1>Hello {{ name }}</h1>
</template>
<script>
export default {
name: "MyVueComponent",
props: {
name: {
type: String,
required: true,
},
mark: {
type: String,
default: "!",
},
},
};
</script>
...
<MyVueComponent name="World" />
事件绑定
React.js
Class component
class MyReactComponent extends React.Component {
save = () => {
console.log("save");
};
render() {
return <button onClick={this.save}>Save</button>;
}
}
Function component
function MyReactComponent() {
const save = () => {
console.log("save");
};
return <button onClick={save}>Save</button>;
}
Vue.js
<template>
<button @click="save()">Save</button>
</template>
<script>
export default {
methods: {
save() {
console.log("save");
},
},
};
</script>
自定义事件
React.js
function MyItem({ item, handleDelete }) {
return <button onClick={() => handleDelete(item)}>{item.name}</button>;
/*
* 应用useCallback钩子来防止在每次渲染时生成新的函数。
*
* const handleClick = useCallback(() => handleDelete(item), [item, handleDelete]);
*
* return <button onClick={handleClick}>{item.name}</button>;
*/
}
...
function App() {
const handleDelete = () => { ... }
return <MyItem item={...} handleDelete={handleDelete} />
}
Vue.js
<template>
<button @click="deleteItem()">{{item.name}}</button>
</template>
<script>
export default {
name: "my-item",
props: {
item: Object,
},
methods: {
deleteItem() {
this.$emit("delete", this.item);
},
},
};
</script>
...
<template>
<MyItem :item="item" @delete="handleDelete" />
</template>
<script>
export default {
components: {
MyItem,
},
methods: {
handleDelete(item) { ... }
},
};
</script>
State
React.js
Class component
class MyReactComponent extends React.Component {
state = {
name: 'world,
}
render() {
return <h1>Hello { this.state.name }</h1>;
}
}
Function component
function MyReactComponent() {
const [name, setName] = useState("world");
return <h1>Hello {name}</h1>;
}
Vue.js
<template>
<h1>Hello {{ name }}</h1>
<!-- 使用组件状态作为prop -->
<my-vue-component :name="name">
</template>
<script>
export default {
data() {
return { name: "world" };
},
};
</script>
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 (
<div>
<span>{this.state.count}</span>
<button onClick={this.increaseCount}>Add</button>
</div>
);
}
}
Function component
function MyReactComponent() {
const [count, setCount] = useState(0);
const increaseCount = () => {
setCount(count + 1);
// setCount(currentCount => currentCount + 1);
};
return (
<div>
<span>{count}</span>
<button onClick={increaseCount}>Add</button>
</div>
);
}
Vue.js
<template>
<div>
<span>{{count}}</span>
<button @click="increaseCount()">Add</button>
</div>
</template>
<script>
export default {
data() {
return { count: 0 };
},
methods: {
increaseCount() {
this.count = this.count + 1;
},
},
};
</script>
双向绑定 (仅Vue.js)
React.js
React没有双向绑定,因此我们需要自己处理数据流
function MyReactComponent() {
const [content, setContent] = useState("");
return (
<input
type="text"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
);
}
Vue.js
<template>
<input type="text" v-model="content" />
</template>
<script>
export default {
data() {
return { content: "" };
},
};
</script>
计算属性
React.js
React.js没有计算属性,但我们可以通过react hook轻松实现
function DisplayName({ firstName, lastName }) {
const displayName = useMemo(() => {
return `${firstName} ${lastName}`;
}, [firstName, lastName]);
return <div>{displayName}</div>;
}
...
<DisplayName firstName="Hello" lastName="World" />
Vue.js
<template>
<div>{{displayName}}</div>
</template>
<script>
export default {
name: "display-name",
props: {
firstName: String,
lastName: String,
},
computed: {
displayName: function () {
return `${this.firstName} ${this.lastName}`;
},
},
};
</script>
...
<DisplayName firstName="Hello" lastName="World" />
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 (
<div>
<span>{count}</span>
<button onClick={increaseCount}>Add</button>
</div>
);
}
Vue.js
<template>
<div>
<span>{{count}}</span>
<button @click="increaseCount()">Add</button>
</div>
</template>
<script>
export default {
data() {
return { count: 0 };
},
methods: {
increaseCount() {
this.count = this.count + 1;
},
},
watch: {
count: function (newCount, oldCount) {
localStorage.setItem("my_count", newCount);
},
},
};
</script>
Children-and-Slot
React.js
function MyReactComponent({ children }) {
return <div>{children}</div>;
}
...
<MyReactComponent>Hello World</MyReactComponent>
Vue.js
<template>
<div>
<slot />
</div>
</template>
<script>
export default {
name: "my-vue-component",
};
</script>
...
<MyVueComponent>Hello World</MyVueComponent>
渲染HTML
React.js
function MyReactComponent() {
return <div dangerouslySetInnerHTML={{ __html: "<pre>...</pre>" }} />;
}
Vue.js
<template>
<div v-html="html"></div>
</template>
<script>
export default {
data() {
return {
html: "<pre>...</pre>",
};
},
};
</script>
条件渲染
React.js
function MyReactComponent() {
const [isLoading, setLoading] = useState(true);
return (
<div>
{isLoading && <span>Loading...</span>}
{isLoading ? <div>is loading</div> : <div>is loaded</div>}
</div>
);
}
Vue.js
<template>
<div>
<!--v-show: 总是渲染,但根据条件更改CSS-->
<span v-show="loading">Loading...</span>
<div>
<div v-if="loading">is loading</div>
<div v-else>is loaded</div>
</div>
</div>
</template>
<script>
export default {
data() {
return { loading: true };
},
};
</script>
列表渲染
React.js
function MyReactComponent({ items }) {
return (
<ul>
{items.map((item) => (
<li key={item.id}>
{item.name}: {item.desc}
</li>
))}
</ul>
);
}
Vue.js
<template>
<ul>
<li v-for="item in items" :key="item.id">
{{item.name}}: {{item.desc}}
</li>
</ul>
</template>
<script>
export default {
props: {
items: Array,
},
};
</script>
Render-Props
React.js
function Modal({children, isOpen}) {
const [isModalOpen, toggleModalOpen] = useState(isOpen);
return (
<div className={isModalOpen ? 'open' : 'close'}>
{type children === 'function' ? children(toggleModalOpen) : children}
</div>)
;
}
Modal.propTypes = {
isOpen: PropTypes.bool,
children: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
}
Modal.defaultProps = {
isOpen: false,
}
...
<Modal isOpen>
{(toggleModalOpen) => {
<div>
<div>...</div>
<button onClick={() => toggleModalOpen(false)}>Cancel</button>
</div>
}}
</Modal>
Vue.js(slot)
<template>
<div v-show="isModalOpen">
<slot v-bind:toggleModal="toggleModalOpen" />
</div>
</template>
<script>
export default {
name: "modal",
props: {
isOpen: {
type: Boolean,
default: false,
},
},
data() {
return {
isModalOpen: this.isOpen,
};
},
methods: {
toggleModalOpen(state) {
this.isModalOpen = state;
},
},
};
</script>
...
<Modal isOpen>
<template v-slot="slotProps">
<div>...</div>
<button @click="slotProps.toggleModal(false)">Close</button>
</template>
</Modal>
生命周期
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 <div>Hello World</div>;
}
}
Function component
function MyReactComponent() {
// componentDidMount
useEffect(() => {}, []);
// componentDidUpdate + componentDidMount
useEffect(() => {});
// componentWillUnmount
useEffect(() => {
return () => {...}
}, []);
// 在渲染之后但在屏幕更新之前同步运行
useLayoutEffect(() => {}, []);
return <div>Hello World</div>;
}
Vue.js
<template>
<div>Hello World</div>
</template>
<script>
export default {
beforeCreate() {},
created() {},
beforeMount() {},
mounted() {},
beforeUpdate() {},
updated() {},
beforeDestroy() {},
destroyed() {},
};
</script>
错误处理
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 <h1>Something went wrong.</h1>;
return this.props.children;
}
}
...
<ErrorBoundary>
<App />
</ErrorBoundary>
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 (
<input
ref={this.ref}
type="text"
value={this.state.content}
onChange={this.setContent}
/>
);
}
}
Function component
function AutofocusInput() {
const [content, setContent] = useState("");
const ref = useRef(null);
useEffect(() => {
if (ref && ref.current) {
ref.current.focus();
}
}, []);
return (
<input
ref={ref}
type="text"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
);
}
Vue.js
<template>
<input ref="input" type="text" v-model="content" />
</template>
<script>
export default {
name: "autofocus-input",
data() {
return { content: "" };
},
mounted() {
this.$refs.input.focus();
},
};
</script>
性能优化
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 <div>...</div>;
}, []);
}
useCallback
function MyItem({ item, handleDelete }) {
const handleClick = useCallback(() => handleDelete(item), [
item,
handleDelete,
]);
return <button onClick={handleClick}>{item.name}</button>;
}
Vue.js
v:once
<span v-once>This will never change: {{msg}}</span>
函数式组件:我们可以将组件标记为 functional ,这意味它无状态 (没有响应式数据),也没有实例 (没有 this 上下文)。
<template functional>
<h1>Hello {{ name }}</h1>
</template>
<script>
export default {
name: "MyVueComponent",
props: {
name: String,
},
};
</script>
keep-alive 组件
<keep-alive> <component :is="view"></component> </keep-alive>
推荐阅读
温故知新 | Vue.js进阶必会,编写你的第一个Vue.js插件
从零开始使用JavaScript制作自己的命令行(CLI工具)
感谢您的阅读和关注,看完三件事:
如果对你有帮助,帮忙文章右下角点个 在看 如果有什么问题欢迎 留言 交流,还可以 转发 ,这是对作者最大的帮助。
以上所述就是小编给大家介绍的《React.js和Vue.js的语法并列比较》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- [译] React 和 Vue 语法并列比较:状态管理
- [译] React.js 和 Vue.js 的语法并列比较
- MySQL实现排名并查询指定用户排名功能,并列排名功能
- Swift语法快速入门(一)之 Swift基础语法
- 在ES6中使用扩展语法有什么好处?它与rest语法有什么不同?
- Python 基础语法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning XML with DOM and Ajax
Sas Jacobs / Apress / 2006-06-05 / USD 39.99
Don't waste time on 1,000-page tomes full of syntax; this book is all you need to get ahead in XML development. Renowned web developer Sas Jacobs presents an essential guide to XML. Beginning XML with......一起来看看 《Beginning XML with DOM and Ajax》 这本书的介绍吧!