Vue 和 React
阿新 • • 發佈:2019-01-08
元件
vue
<template> <div class="hello"> <h1>{{msg}}</h1> <button @click="handleClick">click</button> </div> </template> <script> export default { name: 'HelloWorld', // 生命週期 created() { }, mounted() { }, updated() { }, props: { }, data() { return { msg: 'Welcome to Your Vue.js App' } }, computed: { // 基於prop或data }, filters: { // 過濾器 }, methods: { handleClick() { } }, watch: { // 監控 }, components: { // 注入元件 } } </script> <style scoped> /* 樣式 */ </style>
react
import React, { Component } from 'react' export default class HelloWorld extends Component { constructor(props) { super(props) this.state = { msg: 'Welcom to React' } this.handleClick = this.handleClick.bind(this) } // 生命週期 componentWillMount() { } componentDidMount() { } componentWillUpdata(nextProps, nextState) { } handleClick() { // 修改狀態 this.setState({ msg: this.state.msg + '!' }) } render() { return ( <div className="hello"> <h1>{this.state.msg}</h1> <button onClick={this.handleClick}>click</button> </div> ) } }
data
vue
- 可以直接修改data
<template>
<div class="hello">
<h2>{{status}}</h2>
<button @click="handleClick">click</button>
</div>
</template>
data() { return { status: 'off' } }, methods: { handleClick() { this.status = this.status === 'off' ? 'on' : 'off' } },
- 使用computed
<template>
<div class="hello">
<h2>{{status}}</h2>
<h2>{{statusInfo}}</h2>
<button @click="handleClick">click</button>
</div>
</template>
data() {
return {
msg: 'Welcome to Your Vue.js App',
status: 'off'
}
},
computed: {
statusInfo() {
return this.status === 'off' ? '關閉' : '開啟'
}
},
react
- 不能使用this.state.msg = 'newVlaue'直接修改,而是使用this.setState({}).
constructor(props) {
super(props)
this.state = {
msg: 'Welcom to React',
status: 'off'
}
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
// 修改狀態
this.setState({
status: this.state.status === 'off' ? 'on' : 'off'
})
}
render() {
return (
<div className="hello">
<h2>{this.state.status}</h2>
<h2>{
this.state.status === 'off' ? '關閉' : '開啟'
}</h2>
<button onClick={this.handleClick}>click</button>
</div>
)
}
methods
vue
在methods選項中定義
methods: {
handleClick() {
// do something
}
},
react
- 在元件類中定義,為了this指向元件例項,需繫結this
import React, { Component } from 'react'
export default class HelloWorld extends Component {
constructor(props) {
super(props)
// 繫結this
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
// do something
}
render() {
return (
<div className="hello">
<button onClick={this.handleClick}>click</button>
</div>
)
}
}
- 如果不再constructor中繫結this,可以使用箭頭函式。若考慮效能,推薦使用繫結的方式
<button onClick={() => this.handleClick()}>click</button>
方法的引數
- vue中,直接傳入即可
<button @click="handleClick('args', $event)">click</button>
methods: {
handleClick(args, event) {
console.log(args)
console.log(event)
}
},
- react中,有兩種方式
<button onClick={(e) => this.handleClick('args', e)}>click</button>
<button onClick={this.handleClick.bind(this, 'args')}>click</button>
顯示和隱藏
vue
使用指令v-if或v-show(頻繁切換顯示隱藏時,使用v-show,因為v-if會重新渲染dom,會損耗效能)
<button @click="handleClick">click</button>
<p v-show="showTip">hei I am here!</p>
data() {
return {
showTip: false
}
},
methods: {
handleClick() {
this.showTip = !this.showTip
}
},
react
使用jsx表示式
import React, { Component } from 'react'
export default class HelloWorld extends Component {
constructor(props) {
super(props)
this.state = {
showTip: false
}
// 繫結this
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState({
showTip: !this.state.showTip
})
}
render() {
return (
<div className="hello">
<button onClick={this.handleClick}>click</button>
{
this.state.showTip ? <p>hei I am here!</p> : null
}
</div>
)
}
}
列表
vue
使用v-for,為提高渲染效能,需提供唯一的key值,不推薦使用index,因為index所對應的值可能會不一樣。
<template>
<div class="hello">
<div v-for="(item, index) in list"
:key="index"
:style="{
width: '70px',
height: '50px',
marginTop: '2px',
background: item
}"
>
{{item}}
</div>
</div>
</template>
data() {
return {
list: [
'red',
'green',
'blue',
]
}
},
react
一般使用map()遍歷陣列,渲染dom
constructor(props) {
super(props)
this.state = {
list: [
'red',
'green',
'blue',
]
}
}
render() {
const { list } = this.state
return (
<div className="hello">
{
list.map((item, index) => (
<div key={index}>{item}</div>
))
}
</div>
)
}
元件之間的通訊
vue
- 父元件向子元件傳遞,通過屬性傳值,子元件使用props選項接收
父元件 App.vue
<template>
<div id="app">
<HelloWorld
:message="fatherInfo"
/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
export default {
name: 'App',
data() {
return {
fatherInfo: '父元件的資訊'
}
},
components: {
HelloWorld
}
}
</script>
子元件 HelloWorld.vue
<template>
<div class="hello">
<p>來自父元件的資訊:{{message}}</p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
message: {
type: String,
default: ''
}
},
}
</script>
- 子元件向父元件傳值,通過自定義事件, this.$emit('name', args)
子元件 HelloWorld.vue
<script>
export default {
name: 'HelloWorld',
mounted() {
this.$emit('sonMsg', this.sonMsg)
},
props: {
message: {
type: String,
default: ''
}
},
data() {
return {
sonMsg: 'I am a son ha ha!'
}
},
}
</script>
父元件 App.vue
<template>
<div id="app">
<HelloWorld
@sonMsg="sonMsg"
/>
<p>來自子元件的資訊: {{sonInfo}}</p>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
export default {
name: 'App',
data() {
return {
sonInfo: ''
}
},
methods: {
sonMsg(msg) {
this.sonInfo = msg
}
},
components: {
HelloWorld
}
}
</script>
react
- 父傳子,也是通過屬性
父元件
export default class App extends Component {
constructor() {
super()
this.state = {
name: 'chen',
}
}
render() {
const { name, buttons, childName } = this.state
return (
<div
<HelloWorld
name={name}
/>
</div>
)
}
}
子元件
export default class HelloWorld extends Component {
constructor(props) {
super(props)
render() {
const { name } = this.props
return (
<div className="hello">
<p>來自父元件: {name}</p>
</div>
)
}
}
- 子傳父,也是通過事件
子元件
componentDidMount() {
this.props.getChildren('I am a child')
}
父元件
constructor() {
super()
this.state = {
fromChild: ''
}
}
getChildren = (val) => {
this.setState({
fromChild: val
})
}
render() {
return (
<div>
<HelloWorld
name={name}
getChildren={this.getChildren}
/>
<p>來自子元件:{this.state.fromChild}</p>
</div>
)
}
react的屬性型別檢測
import PropTypes from 'prop-types';
class App extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
App.propTypes = {
name: PropTypes.string
};
資料雙向繫結
vue
vue可以直接使用指令v-model實現資料的雙向繫結
<input v-model="values"/>
<p>input的值:{{values}}</p>
data() {
return {
values: ''
}
},
react
react需要手動實現資料雙向繫結
constructor(props) {
super(props)
this.state = {
values: ''
}
}
handleChange = (event) => {
this.setState({
values: event.target.value
})
}
render() {
return (
<div className="hello">
<input onChange={this.handleChange}/>
<p>input的值:{this.state.values}</p>
</div>
)
}
slot和高階元件
封裝元件時,只封裝一個外殼,如封裝一個容器,容器裡還可以裝其它元件。vue使用slot,react可以使用高階元件。
vue
Container.vue
<template>
<div class="container">
<slot></slot>
<slot name="green"></slot>
<slot name="blue"></slot>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.container {
width: 200px;
height: 200px;
padding: 2px;
border: 1px solid red;
}
</style>
HelloWorld.vue
<template>
<div class="hello">
<Container>
<div>I have no name</div>
<div slot="green">I am green</div>
<div slot="blue">I am blue</div>
</Container>
</div>
</template>
<script>
import Container from './Container'
export default {
name: 'HelloWorld',
components: {
Container
}
}
</script>
react
- react中也有類似的做法,{props.children}
import React, { Component } from 'react'
const Container = (props) => (
<div>
{props.children}
</div>
)
export default class HelloWorld extends Component {
render() {
const { name } = this.props
return (
<div className="hello">
<Container>
<p>I am a child</p>
</Container>
</div>
)
}
}
- react 中的高階元件
高階元件就是一個函式,且該函式接受一個元件作為引數,並返回一個新的元件
import React, { Component } from 'react'
const container = (Comp) => {
return class extends Component {
render() {
return <Comp {...this.props} />
}
}
}
const Child = () => (
<div>child</div>
)
const Container = container(Child)
export default class HelloWorld extends Component {
render() {
return (
<div className="hello">
<Container />
</div>
)
}
}
其他
vue中的computed和watch
computed在DOM載入後馬上執行,watch只有在資料變化時才執行;
computed在資料未發生變化時,優先讀取快取。watch在資料變化時來執行非同步操作時,非常有用。