1、安装
?
使用Vue脚手架安装项目
- 保证全局已装有vue
npm i vue -g 安装后自带vue-cli - 使用vue中的命令
vue create 项目名称 创建项目即可 - vue默认端口
8080 - 启动项目使用
npm run serve - 目录结构
- public (最大的index文件,vue单文件模式基于此文件中的index.html)
- src (页面、路由、api、vuex等操作都在其中)
- main.js:项目入口文件,项目中最高的js层
- App.vue:根组件 (vue整个页面的根)
- components:用于封装功能组件,用来多页面复用
- assets:静态资源目录(图片、视频、音频等)
- router:用于写入页面路由管理
- store:管理vuex
- config:用于写入项目中的配置(接口地址的配置等)
- views:用于存放视图的组件(页面)
?
使用Reactan安装项目
- 可以先全局安装
$ npm install -g create-react-app - 使用全局安装后的create-react-app安装项目
$ create-react-app 项目名称
但更推荐使用npx进行安装
npx create-react-app 项目名称 - react中默认端口是
3000 - 可以使用
yarn start 启动项目 (如果未安装yarn使用 npm yarn i -g 安装) - 或者使用
npm start 启动项目 - 目录结构
- public:(最大的index文件,react单文件模式基于此文件中的index.html)
- src(页面、路由、api、vuex等操作都在其中)
总结:
? ?
2、创建组件
?
使用Vue创建组件
vue有全局组件和局部组件
<template>
<div>
<my-component></my-component>
</div>
</template>
var Child = {
template: '<div>hello world!</div>'
}
new Vue({
components: {
'my-component': Child
}
})
?
使用React创建组件
react有函数式组件和class组件
import React from 'react'
import ReactDOM from 'react-dom'
import Child from './Child'
class App extends React.Component {
render () {
return (
<>
<h1>hello class</h1>
<h2>你好 中国</h2>
<Child></Child>
</>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
)
总结:
- vue和react都是支持组件化开发
- vue和react都是通过创建虚拟dom,最后挂载到一个标签内
- vue有区分全局组件和局部组件
- vue每次引入组件都需要先通过
components 在局部注册组件,才能使用 - react可直接通过
impont 导入组件,在父组件中通过名字使用即可(组件名称需要大写)
? ?
3、父组件通过属性向子组件传值
?
在Vue中父组件通过属性向子组件传值
在父组件调用子组件标签上设置属性进行传值 子组件中使用props来接收 props有三种写法
- 1.props的值为数组,数组的元素为自定义的属性名
- 2.props的值为对象,对象的key值为自定义的属性名,value值为数据类型
- 3.props的值为对象,对象的key值为自定义的属性名,value值为一个新的对象
- 新对象的key值可以有 type,表示数据类型
- 新对象的key值可以有 default,表示默认数据(如果默认是为对象或者数组,default为函数,返回对象或数组)
- 新对象的key值可以有 required ,表示这个属性是必须传递的
- 新对象的key值可以有 validator ,自定义验证函数会将该 prop 的值作为唯一的参数代入(可以设置条件,限制传入的值)
props: {
day: {
default: '日',
type: String
}
},
?
在React中父组件通过属性向子组件传值
在子组件中使用this.props.name 接收到值
可通过defaultProps 设置props默认值 在类组件内
static defaultProps = {
name:'张三'
}
?
可下载使用prop-types 包设置props类型 在类组件中
import PropTypes from 'prop-types'
App.propTypes = {
name: PropTypes.string.isRequired,
num: PropTypes.oneOfType([
PropTypes.string.,
PropTypes.number
]).isRequired
}
总结:
- react和vue使用同理 父传子通过标签属性向子组件传参,子组件通过props接收,只是接收写法有些不同。
- vue设置默认值直接通过props对象写法,其中写入default,而react设置默认值需要设置静态属性
defaultProps - vue中设置数据类型直接通过对象中的type设置,而react设置需要安装并导入第三方
prop-types 使用才能设置数据类型 ? ?
4、子组件向父组件传值
在vue中子向父传值
<div> <child @anlarge-text='bigger'></child></div>
<script>
var child = {
template: `<button @click="$emit('anlarge-text',9)">点我给父组件字体加9px</button>`,
}
export default {
data(){
return {
fontSize:12
}
},
component:{child},
methods:{
bigger(n){
this.fontSize += n
}
}
}
</script>
在react中子向父传值
class Title extends Component {
state = {
num: 1000
}
render () {
return (
<>
<h1>标题-{ this.props.name }</h1>
<button onClick = { () => {
this.props.fn(this.state.num)
} }>发送</button>
</>
)
}
}
class App extends Component {
getData = (val) => {
console.log(val)
}
render() {
return (
<>
<Title name="title" fn = { this.getData }></Title>
</>
)
}
}
export default App
总结:
- 在vue中实现子传父,先得在父组件定义一个函数方法,用来接收子组件传过来的值,子组件通过
$emit() 调用父组件上的方法,传入父组件需要的参数 - 在react中的子传父实际上还是在父传子,父组件中定义方法写在属性中,子组件通过
this.props.事件名 调用父组件传入的方法,在方法内进行传值 ? ?
5、父组件通过标签内容向子组件传入内容
?
在Vue中子组件可通过slot 插槽接收
// 父组件
<app-layout>
<h1 slot="header">这里可能是一个页面标题</h1>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
<p slot="footer">这里有一些联系信息</p>
</app-layout>
// 子组件
<div class="app-layout">
<slot name="header"></slot>
<slot name="footer"></slot>
</div>
- 作用域插槽
作用域插槽是一种特殊类型的插槽,作用域插槽会绑定了一套数据 ,父组件可以拿这些数据来用
// 父组件
<child>
<div slot-scope="props">
<div>父组件</div>
<h3>{{ props.text }}</h3> // 我是子组件中的内容
</div>
</child>
// 子组件
<div class="child">
<slot text="我是子组件中的内容"></slot>
</div>
?
在React中子组件可通过props.children 来接收
class App extends Component {
render(){
return (
<Content>向子组件传入的内容</Content>
)
}
}
export default class Content extends Component {
render(){
return(
<h1>{this.props.children}</h1>
)
}
}
总结:
- 在vue中只需要写入
<slot/> 匿名插槽,那父组件在调用子组件的标签内写入任何内容都会被子组件解析 - 在react中子组件只需要使用
this.props.children 即可访问父组件向子组件标签内传入的内容 ? ?
6、存放数据、状态
?
在Vue中存放数据
在vue中数据都是存放在data中,需要给data设置成函数,将数据return出来,可以保证组件在被多次创建后不会造成数据互相影响污染。
data(){
return {
name : "张三"
}
}
?
在Reac中存放状态
export default class Child extends Component {
state = {
count: 100
}
render() {
return (
<>
<div>
{this.state.count}
</div>
</>
)
}
}
总结:
- vue可直接通过 this.name 进行修改数据
- react修改数据需要通过setState让他触发render,从而视图重新渲染更新,react官方不允许直接通过this.state去修改数据
? ?
7、渲染数据
?
在Vue中渲染data中数据 ( {{ }} )
// 使用胡子语法
<p>{{name}}</p>
// 使用 v-text 和 v-html(可解析标签,少用,可能引发XSS攻击)
<p v-text="name"></p>
<p v-html="a"></p>
<script>
export default {
data(){
return{
name:'张三',
a:'<a href="http://www.baidu.com">百度</a>'
}
}
}
</script>
在React中渲染state状态数据
export default class App entends Component {
state={
name:'张三'
}
render(){
return(
<>
<p>{this.state.name}</p>
</>
)
}
}
总结:
?
在Vue中通过条件渲染数据( v-if 或 v-show )
v-if 可让标签初始判断是否需要加载 v-show 就是给标签加上一个display:none样式
// 第一种 通过v-if v-else 控制显示标签 多个判断可使用v-else-if
<div v-if="flag">
<span>白天</span>
</div>
<div v-else>
<span>晚上</span>
</div>
// 第二种 通过三元运算符控制显示内容
<h1>{{flag ? "白天" : "晚上"}}</h1>
<script>
export default {
data(){
return{
flag:true
}
}
}
</script>
在React中通过条件渲染数据
export default App extends Component{
state = {
flag:true
}
render(){
if(flag) {
return(
<><h1>白天</h1></>
)
}
else {
return(
<><h1>晚上</h1></>
)
}
}
}
export default App extends Component{
state={ flag:false}
render(){
return(
<h1>{flag ? '白天' : '晚上'}</h1>
)
}
}
总结:
- 在vue中提供了
v-if 和v-else 来控制渲染显示的标签 - 在react中不推荐使用流程控制语句来实现,可在
{ } 内写入三元运算符形式控制显示内容
?
在Vue中循环渲染数组对象数据( v-for )
<template>
<ul>
// 需要将哪个标签遍历多次 v-fro 就加在哪个标签内
// 其中的key值是为了提高性能,区分渲染的标签,也可使用item或数据中的id属性,只要是唯一的
<li v-for="(item,index) in list" :key="index">{{item}}</li>
</ul>
</template>
<script>
export default {
data(){
return {
list:[1,2,3,4,5,6]
}
}
}
</script>
在React中循环渲染数组对象数据
export default class App extends Component {
state = {
list: [
{
brand: '奔驰',
items: [ 'S系列', 'E系列' ]
},
{
brand: '奥迪',
items: [ 'A系列', 'Q系列' ]
}
]
}
render(){
return(
<>
<ul>
{
this.state.list.map((item,index) => (
<li key={item.brand}>{item.brand} </li>
{
item.map((itm,idx) => (
<div key={idx}>{itm}</div>
))
}
))
}
</ul>
</>
)
}
}
总结:
- 在vue中提供了
v-for 给我们循环渲染数据 - 在react中我们需要使用
js 的语法来实现循环渲染数据
? ?
8、事件
在vue中使用事件
<button @click="add($event)">按钮</button>
export default {
data(){
},
methods:{
add(event){
console.log(1)
}
}
}
在react中使用事件
export default class App extends Component {
add(event){
console.log(1)
}
render(){
return(
<><button onClick={this.add.bind(this)}></button></>
)
}
}
总结:
- 在vue中需要在
methods 中写入方法函数,在标签内通过v-o事件 语法糖为 @事件 去设置事件调用 - 在react中设置了方法函数后,在标签中通过
on事件 调用,注意会有this 指向问题,我们可以给他手动修改this 或者函数使用箭头函数,让他使用外部的this - 在vue中需要通过
$event 向方法传入事件对象 - 在react中会默认传入
event 事件对象,且这个事件对象是 - 在react中可直接通过
事件 = {()=>{}} 写入逻辑 ? ?
9、input输入框的数据绑定
在vue中实现input框和数据的绑定
// v-model 是 :value 和 @input 两个的简写 从而实现数据的双向绑定
<input type="text" v-model="msg"/>
export default {
data(){
return {
msg:''
}
}
}
在react中实现input框和数据的绑定
export default class App extends Component {
state = { userName:'' ,pwd:''}
changeName(event){
this.setState({
userName:event.target.value
})
}
changeVal = (event) => {
this.setState({
[event.target.name] : event.target.value
})
}
render(){
return(
<>
<input
type="text"
value={this.state.userNmae}
onChange={this.changeName.bind(this)}
/>
<input
type="text"
value={this.state.pwd}
onChange={this.changeVal}
/>
</>
)
}
}
总结:
- vue可以直接通过
v-model 实现数据的双向绑定 - react可以通过
value 属性绑定state 中的数据,再通过onChange 事件穿入事件对象,再根据事件对象修改state 中的值 ? ?
生命周期
?
Vue生命周期
beforeCreate 实例创建前;
create 实例创建后;
beforeMount 挂载前mounted 挂载后;
beforeUpdate 数据更新前updated 数据更新完成后beforeDestroy 销毁之前;
destroyed 销毁之后
?
React生命周期
挂载 当组件实例被创建并插入 DOM 中时
constructor()
- react组件的构造函数在挂载之前调用 ——做些初始化操作,可在其设置初始
state ,但官方不建议在这生命周期操作,这些初始化操作应在componentDidMount() 中使用; static getDerivedStateFromProps()
- 会在调用
render() 前调用,并在初始化挂载及后续更新都会调用—— render()
- 此方法是class组件中必须的——被调用时,它会检查
this.props 和this.state 的变化 componentDidMount()
- 在组件挂载后(插入DOM树中),立即调用—— 可请求数据,依赖DOM元素的初始化也可写在这里
更新 当组件的props或state发生变化时会触发更新
static getDerivedStateFromProps() shouldComponentUpdate()
- 官方建议使用内置的
PureComponent 组件,不使用此方法——设置组件重新渲染是否受state 和props 的影响。默认每个状态更改都会重新渲染,大多数情况下应该褒词这个默认行为。shouldComponentUpdate(nextProps, nextState) 有两个参数,在渲染新的props 和state 前此方法会被调用,判断旧数据是否和新数据不同,返回false 就代表不更新,注意:此方法不会阻止自己的组件内的state改变更新视图重新渲染 render() getSnapshotBeforeUpdate()
- 在最近一个渲染输出(提交到DOM节点)前调用——能在组件发生更改之前从DOM中获取信息,(如滚动位置),这个生命周期的任何返回值都将作为参数传递给
componentDidUpdare() componentDidUpdate(prevProps, prevState, snapshot)
- 在更新发生后立即调用,初始化渲染的不会被调用——当组件更新时,可在此操作DOM。可以在此和将当前的props与之前的props比较(例如,如果props没有改变,则可能不需要网络请求)
卸载 当组件从DOM中移除时
componentWillUnmount()
- 会在组件卸载销毁前调用——在此执行清除操作,例如定时器,取消网络请求或清理
componentDidMount 中创建的监听等
错误处理 当渲染过程,生命周期,或子组件的构造函数中抛出错误时
static getDerivedStateFromError() componentDidCatch(error, info)
- 此生命周期在后代组件抛出错误后被调用—— 可以在组件内任何位置捕获JS错误记录捕获的错误并,显示对应的UI错误提示给用户,而不是崩溃的组件树
|