React.js和Vue.js都是很好的框架。並且Next.js和Nuxt.js甚至將它們帶入了一個新的高度,這有助於咱們以更少的配置和更好的可維護性來建立應用程序。可是,若是你必須常常在框架之間切換,在深刻探討另外一個框架以後,你可能會輕易忘記另外一個框架中的語法。在本文中,我總結了這些框架的基本語法和方案,而後並排列出。我但願這能夠幫助咱們儘快掌握語法,不過限於篇幅,這篇文章只比較React.js和Vue.js,下一篇再談Next.js個Nuxt.js。javascript
Github: https://github.com/oahehc/rea...
React.jshtml
ReactDOM.render(<App />, document.getElementById("root"));
Vue.js前端
new Vue({ render: (h) => h(App), }).$mount("#root");
Class componentvue
class MyReactComponent extends React.Component { render() { return <h1>Hello world</h1>; } }
Function componentjava
function MyReactComponent() { return <h1>Hello world</h1>; }
<template> <h1>Hello World</h1> </template> <script> export default { name: "MyVueComponent", }; </script>
React.jsreact
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.jsgit
<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" />
Class componentgithub
class MyReactComponent extends React.Component { save = () => { console.log("save"); }; render() { return <button onClick={this.save}>Save</button>; } }
Function componentweb
function MyReactComponent() { const save = () => { console.log("save"); }; return <button onClick={save}>Save</button>; }
<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>
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>; }
<template> <h1>Hello {{ name }}</h1> <!-- 使用組件狀態做爲prop --> <my-vue-component :name="name"> </template> <script> export default { data() { return { name: "world" }; }, }; </script>
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> ); }
<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>
React沒有雙向綁定,所以咱們須要本身處理數據流
function MyReactComponent() { const [content, setContent] = useState(""); return ( <input type="text" value={content} onChange={(e) => setContent(e.target.value)} /> ); }
<template> <input type="text" v-model="content" /> </template> <script> export default { data() { return { content: "" }; }, }; </script>
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" />
<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" />
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> ); }
<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>
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>
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>
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>
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>; }
<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(); } }
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)} /> ); }
<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>
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>; }
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>
文章首發《前端外文精選》微信公衆號
若是對你有所啓發和幫助,能夠點個關注、收藏、轉發,也能夠留言討論,這是對做者的最大鼓勵。
做者簡介:Web前端工程師,全棧開發工程師、持續學習者。
繼續閱讀其餘高贊文章