前端学习踩坑(1)
前端学习踩坑(1)
笔者这两天正在进行JavaScript与TypeScript基础项目的编写,涉及到的问题多为基础
关于TS与JS的爱恨情仇
通过属性的key访问value
众所周知,js中我们在定义了某个对象的属性的前提下,可以直接使用key来访问该属性的value,如下:
1 | class User { |
在显式的类定义下,ts也可以做到相同的事情,写法仅仅是添加一个属性的类型
1 | class User{ |
但是在某些情况下,我们需要遍历某个对象里的所有属性,并且可能这个对象的定义对于我们来说是非显式定义的,即我们也不知道他的类型,所以我们在ts中便出现了以下的问题:
1 | function span(user : object) { |
由于引用的user类型是我们自己显式定义的User,我们可以使用以下方法来解决:
1 | function span <T extends object> (user : T) { |
这是使用泛型来解决这种报错的技巧,同时我们也可以使用断言:
1 | function span2 (user : User) { |
keyof
在ts中,我们可以使用keyof关键字来获取一个对象中所有的key,然后返回一个新的联合类型
1 | class User{ |
typeof
通过使用typeof关键字,我们可以获得一个对象的type,这常常被使用在根据对象类型的不同而编写分支语句的情况下。
回到上文
1 | function span2 (user : User) { |
通过使用typeof user,我们获得了User类型,再通过使用keyof User,我们获得了User中的所有key的联合类型,这样我们就可以正常的遍历对象中的属性了。
所以说,我们也可以这么写
1 | function span3 (user : User) { |
为对象动态增添属性
这听起来很简单,在js中你只需要object[key] = value,这个对象就优雅的新增了一个属性,但是在ts中,这可让我犯了难。
我尝试使用一个自定义的封装好的{key : any, value : any}对象的数组来存储新增的类型,只需要每次新建一个这个对象的实例,然后push进数组就大功告成了。
但是!有一个很严重的问题,对象中属性的存储是一种字典的键值对的存储模式,而不是数组,即对于相同的key,永远只能存在一个value,但是数组的话便会一直新增实例的数量。(这也是我找了一早上的bug,为什么越用越卡)
惨案现场,浏览器真是最好的调试器!
所以我们有一个更加优雅的方式,新建一个类用于封装 + 模拟字典
1 | class Methods { |
可以看到,我们通过使用数组来当做key,这使得我们在添加时,能够很容易的直接添加新的属性,同时也能直接修改key对应的value
1 | class Methods { |
React组件
函数式组件
我们可以通过以下两种方式创建函数式组件:
1 | // 1.创建函数式组件 |
然后将组件渲染出来
1 | ReactDOM.render(<Demo />,document.getElementById("test")); |
组件的首字母必须是大写,并且有返回值
在渲染的时候必须<组件名 />
即React先解析组件标签,若组件的标签为小写开头,则自动匹配HTML中已经预设好的标签,只有当标签为大写字母开头,React才会解析组件标签并找到相应的组件。在发现组件是函数定义的后,调用函数,并将返回的虚拟DOM转化为真实DOM,并渲染在页面中。
类式组件
1 | // 1.创建类式组件 [必须继承React.Component] |
然后将组件渲染出来:
1 | ReactDOM.render(<MyComponent/>, document.getElementById('text')); |
渲染过程和上面基本相同。
下面是一个基本的类组件的例子:
1 | class Weather extends React.Component { |
添加属性时,可以使用增加父类中的state属性来修改,但是更加容易的方法是直接在子类中继承父类的state属性并直接进行增删改。
添加方法时,需要考虑到一个问题,非静态方法应该由类的实例来调用,若是在虚拟dom中直接触发,会导致click中的this未定义,所以我们要首先将类中的方法的this进行赋值,即使用bind,才能正确的调用函数。
为了简化,我们可以使用箭头函数会搜寻外侧的实例作为this的特性,对函数中的this进行正确的赋值,简化后的代码如下:
1 | class Weather extends React.Component { |
Jest单元测试
通过使用Jest + jsdom,可以模拟dom进行我们自编写vue组件的测试。
在终端使用
1 | jest --init |
在其中的测试环境中选择jsdom,并安装对应依赖
1 | "dependencies": { |
1 | const {Vue} = require("../src/index.js"); |
引入测试类后,通过对document.body.innerHTML的修改,创建不同的dom用于测试。在这个测试方法中,我们测试了v-text组件的实现。在正常运行的情况下,<p>
标签中应该有msg的元素,即’hello world’,使用toMatch即可判断结果。