组件
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在数据变化时来执行异步操作时,非常有用。