自学内容网 自学内容网

react-问卷星项目(2)

流程

husky

一个git hook 工具,即在git commit之前执行自定义的命令,将规范流程化,如执行代码风格的检查,避免提交非规范的代码,在github搜索即可。

这两条是接着执行的,表示创建husky,在文档说明里也有,我按照视频里的指令执行会显示初始化失败,这两条我自己用的没问题。

npm install --save-dev husky
npx husky init

这个pre-commit就是表达在提交之前要执行什么操作,这个foramt是开始在package.json中写的规则之一,这里依次写上想要在commit之前执行的规则就行,最后还加一个git add .是因为format是有重写功能的,所以加上这一句可以在出错的时候更改后再次提交。

记得第二句的箭头是>>表示追加,要是两句都是>则后一句会覆盖前一句,可以在.husky/pre-commit文件中查看是不是有相应的提交指令,这控制台或者直接在这个文件中添加都是可以的。

echo "npm run format" > .husky/pre-commit
echo "git add ." >> .husky/pre-commit 

添加完毕后按照流程执行到commit,可以看控制台是不是有执行相关指令的提示。

commit lint

限制commit提交的规范(不是非必需)

还是直接复制粘贴执行就行,有问题的可以去github找一下看相关文档,前两句是创建,后一句同样是添加一个在.husky下面名叫commit-msg的文件,可以去看一下有没有这个文件

npm install --save-dev @commitlint/{cli,config-conventional}

"export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js

"npx --no -- commitlint --edit \$1" > .husky/commit-msg

在这里我碰到一个问题,就是前面创建的指令中是创建了一个名为./commitlint.config.js的文件,但是这个文件会报错,视频里教的是保存一下就行,我试了下,保存后确实不报错了,但是提交的时候还是会报错,我觉得这里可能和我前面用脚手架创建项目的时候选的一些配置有关,并不支持es6的格式,所以按着其他的文件改了下,还是有红,但是再次提交的时候就没报错了。

export default { extends: ['@commitlint/config-conventional'] };
// 改为
module.exports = { extends: ["@commitlint/config-conventional"] };

然后再说明下这个的作用,就是用来规范commit的写法的,比如下面这两句,第一句会报错,第二句就不会了,前面添加的chore是主题。

git commit -m"commit-lint"

git commit -m"chore: commit-lint"

主题可以按照前面那个下载的路径去相应的文件夹下查看,node_modules/@commitlint/config-conventional/lib/index.js 我这个项目中的路径是这样的,反正就是找到index.js文件,找到类似下面这一部分

JSX语法和组件

JSX语法

JSX是JS的扩展,写在JS代码里面,组件的UI结构,类似HTML结构,只是HTML不能写在js中,JSX可以写在js中,已成为ES规范,不是React独有,其他框架中也能写,比如Vue3。

先看文件后缀名,用js语法的时候文件后缀为.js,用js写react的时候后缀要更换为.jsx。同理用ts语法的时候文件后缀为.ts,用ts写react文件的时候后缀要更换为.tsx。所以在tsx后缀文件中看到了类似HTML语法的内容实际上就是JSX语法。

JSX标签和HTML标签的不同

  • 小写是常见的html组件,大写是自定义组件
  • 非闭合组件在JSX是违法,所有标签必须是两个一起闭合或者自闭合,比如input
  • 每个JSX片段中只能有一个根节点,跟vue文件单节点相似。因为片段中可能相互嵌套,那很多作为根节点的div除了作为容器可能就没有意义,可以使用Fragment,即一个空的开始和结束,不能添加任何属性。

属性

  • class改为className,for要改为htmlFor。两个都是因为class和for是关键字所以要另外其名避免这个问题。
  • style要使用JS对象(不能使用字符串),并且其中的key要驼峰写法,即前面的属性,比如HTMl中写为background-color,在JSX中写为backgroundColor
style="color:red"
//更换为
style={{ color: "red" }}

事件

  • 使用onXxx的形式
  • 必须传入一个函数(是fn而非fn())
  • 注意Typesript类型
function App() {
  const fn = () => {
    console.log("click");
  };
  return (
         <div>
          <button onClick={fn}></button>
        // 不要写onClick={fn()}
        </div>
}

TypeScript基础知识

在线转换网址

ts方便在开发环境下有类型及早识别错误,提高开发效率和代码稳定性。

// ts中引入了数据类型
const n: number = 100
const s :string = "s"

function fn(a: number) {
    return a + 100;
}
fn(10)

// js中相应的设置不需要设置类型
var n = 100;
var s = "s";

可定义泛型类T,T的类型根据传入的参数进行改变,如果传值不符合这个类型也会报错,ts中<>表示的就是泛型,比如下面这个。传进去T为string类型

function fn<T>(info: T) {
    console.log(T);
}
fn<String>("Hello")


class foo{
    info: string
    setInfo(newInfo: string) {
        this.info = newInfo
    }
}
const F1:foo = new foo();
// 上面的类转换成js格式如下
// 这个写法是es6之前没有块级领域时的写法,即匿名立即执行函数表达式(匿名 IIFE)
var foo = /** @class */ (function () {
    function foo() {
    }
    foo.prototype.setInfo = function (newInfo) {
        this.info = newInfo;
    };
    return foo;
}());
var F1 = new foo();

如果有两个参数,比如下面这种情况,非标准格式,想要表达的意思就是前面第二点说过,要传入一个函数fn而不是fn(),这里如果有另一个参数,那只写成fn就会报错,有个解决方法如下,写成函数调用的形式就不会违反传入参数只能是函数这个规则了。

const fn = (event: MouseEvent<HTMLButtonElement>,name:string){
 console.log('clicked...',name)   
}
onclick = {
    event => {
    fn(event,'双越')
}}

插入JS变量

  • 使用{xxx}可以插入JS变量,函数,表达式,比如src或者是onClick等
  • 可插入普通文本,属性
  • 可用于注释,在大括号中可以插入注释
{/* JSX注释内容 */}
{/* <p></p> */}

条件判断

  • 使用&&
  • 使用三元表达式
  • 使用函数
const flag = true;
<div>
    /* flag为true展示p标签 */
    {flag && <p>Hello</p>}
</div>

  //  自定义标签大写,小写会报错
  function Hello() {
    if (flag) return <p>Hello</p>;
    return <p>你好</p>;
  }

<div>
    {flag && <p>Hello</p>}
    {flag ? <p>Hello</p> : <p>你好</p>}
    <Hello></Hello>
</div>

循环

  • 使用map执行循环
  • 每个item元素需要key属性
  • key在同级别唯一(强烈不建议使用index作为key,而是使用可以保证唯一的属性)
  const list = [
    { id: "1", name: "zs" },
    { id: "2", name: "ls" },
    { id: "3", name: "ww" },
  ];

<div>
          {list.map((user) => {
            const { id, name } = user;
            return <li key={id}>{name}</li>;
          })}
        </div>

实战开发

都比较基础,我对自己不理解的会另外补充,别的基本就是代码直接贴上去。

  • 循环出一个基础页面加导入样式
import React from "react";
import "./App.css";

function App() {
  // 列表页
  const questionList = [
    { id: "q1", title: "问卷1", isPublished: true },
    { id: "q2", title: "问卷2", isPublished: false },
    { id: "q2", title: "问卷3", isPublished: false },
    { id: "q2", title: "问卷4", isPublished: false },
  ];
  function edit(id: string) {
    console.log(id);
  }
  return (
    <div>
      <h1>问卷列表页</h1>
      <div>
        {questionList.map((list) => {
          const { id, title, isPublished } = list;
          return (
            <div key={id} className="list-item">
              <strong>{title}</strong>
              <br />
              {/* {条件判断} */}
              {isPublished ? (
                <span style={{ color: "green" }}>已发布</span>
              ) : (
                <span>未发布</span>
              )}
              <button
                onClick={() => {
                  edit(id);
                }}
              >
                编辑问卷
              </button>
            </div>
          );
        })}
      </div>
    </div>
  );
}

export default App;

组件和props

组件式React的基础,props是组件的基础

  • 组件就是一个UI片段
  • 拥有独立的逻辑和显示,不仅仅是静态的,而是有创建销毁等“生命周期”
  • 组件可大可小,可嵌套
  • 组件的价值和意义
    • 组件嵌套来组织UI结构,和HTML一样无学习成本
    • 组件拆分,利于代码维护,和多人协作开发
    • 可封装公共组件(或第三方组件)服用代码,提高开发效率
  • React支持class组件,函数组件,但在React16之后,React推崇函数组件

组件抽离

App是项目根节点,所有内容集中在这个位置不太好,所以接下来将所有组件抽离出来。

新建List1.tsx,代码内容如下,即将需要抽离的部分放入到这个FC结构中,记得FC是数据类型,这里规定了房间去的内容为FC,所以里面一定要至少有一个标签。

import React, { FC } from "react";
// FC是一个TS类型,可以通过Import type获取
// import type { FC } from "react";

const List1: FC = () => {
  const questionList = [
    { id: "q1", title: "问卷1", isPublished: true },
    { id: "q2", title: "问卷2", isPublished: false },
    { id: "q2", title: "问卷3", isPublished: false },
    { id: "q2", title: "问卷4", isPublished: false },
  ];
  function edit(id: string) {
    console.log(id);
  }
  return (
    <div>
      <h1>问卷列表页</h1>
      <div>
        {questionList.map((list) => {
          const { id, title, isPublished } = list;
          return (
            <div key={id} className="list-item">
              <strong>{title}</strong>
              <br />
              {/* {条件判断} */}
              {isPublished ? (
                <span style={{ color: "green" }}>已发布</span>
              ) : (
                <span>未发布</span>
              )}
              <button
                onClick={() => {
                  edit(id);
                }}
              >
                编辑问卷
              </button>
            </div>
          );
        })}
      </div>
    </div>
  );
};
export default List1;

更改存放了List1的组件样式的文件名称,尽量保持和组件内容一致,然后在App中如下导入使用

import React from "react";
import "./List1.css";
import List1 from "./List1";

function App() {
  // 列表页
  return (
    <>
      <List1></List1>
    </>
  );
}

export default App;

React开发者工具

是一个Chrome插件,Vue也有一个类似的调试插件

官网搜索chrome react dev tool,因为是外网所以搜索不到,我这里本身有翻墙,所以直接在chrome搜索的,搜索到官网点击进去下载即可。

不知道是什么原因,没看到相关的插件,直接打开chrome的右上角三个点,选择管理扩展插件看看有没有刚刚下载的那个工具的名字,没有的话直接商店搜索然后下载应用就可以,成功的话点开开发界面右边那个箭头应该有相应的紫色图标,点击和图中一致的即可。但如图所示,我这边并没有展开,相应的原因不清楚,我选择直接看浏览器元素。

找到原因了……因为中间漏了一节课,老师在那节课中用一个组件封装包裹起来了,所以会显示四条用另一个组件封装的数据,这里就不多加了。总结一下意思就是,如上面那个图所示,只用List封装了一个列表,而里面的内容并没有展示出来,老师展示的效果是List里面的N条数据都用固定的组件模版返回,所以展示出来的是List下面还有N条数据,每个数据以封装他们的组件命名。

JSX和Vue模版区别

比较有代表性的而不是全部

  • 判断:Vue模版使用v-if指令
  • 循环:Vue模版使用v-for指令
  • 设计理念:React-能用JS就用JS(需要JS基础扎实),Vue自定义很多指令,方便初学者记忆和学习,不过现在vue3也能很好的支持JSX语法。


原文地址:https://blog.csdn.net/BHDDGT/article/details/142133877

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!