跳到主要内容

15 篇博文 含有标签「前端」

查看所有标签

1. 创建项目

npm i -g @tarojs/cli

npm info @tarojs/cli

>taro init 01-base-taro
Taro 即将创建一个新项目!
Need help? Go and open issue: https://tls.jd.com/taro-issue-helper

? 请输入项目介绍 01-base-taro
? 请选择框架 (Use arrow keys)
React
PReact
Vue3
Solid
? 是否需要使用 TypeScript (Y/n)n
? 是否需要编译为 ES5No
? 请选择 CSS 预处理器(Sass/Less/Stylus) (Use arrow keys)
Sass
Less
Stylus

? 请选择包管理工具 (Use arrow keys)
❯ yarn
pnpm
npm
cnpm
? 请选择编译工具 (Use arrow keys)
Webpack5
Vite
? 请选择模板源 (Use arrow keys)
Gitee(最快)
Github(最新)
CLI 内置默认模板
自定义
社区优质模板源
❯ 默认模板
mobx
pwa
react-NutUI(NutUI + React 模板(https://nutui.jd.com/react/))
react-native
react-native-harmony
redux
(Move up and down to reveal more choices)


✔ 初始化 git 成功
执行安装项目依赖 yarn install, 需要一会儿...
yarn install v1.22.22
info No lockfile found.
[1/4] Resolving packages...
warning @tarojs/helper > @swc/register@0.1.10: Use @swc-node/register instead

...



[4/4] Building fresh packages...
success Saved lockfile.
$ husky
Done in 145.78s.
安装项目依赖成功
创建项目 01-base-taro 成功!
请进入项目目录 01-base-taro 开始工作吧!😝
(base) jiexu:002-coder-why-taro/ (master✗) $ cd 01-base-taro                                                                                   [20:56:14]
(base) jiexu:01-base-taro/ (master✗) $ yarn [21:00:14]
yarn install v1.22.22
[1/4] 🔍 Resolving packages...
success Already up-to-date.
$ husky
Done in 0.84s.

1.1 项目运行

  • VSCODE需要安装插件:ESLint, Prettier

  • 用H5打开

yarn dev:h5
  • 小程序打开
yarn dev:weapp

1.1.1 编译运行

  • Taro编译分为 devbuild模式

    • dev 模式(增加 --watch参数) 将会监听文件修改
    • build模式(去掉 --watch参数) 将不会监听文件修改,并会对代码进行压缩打包
  • dev命令启动Taro项目的开发环境

    • pnpm run dev:h5 启动H5端
    • pnpm run dev:weapp 启动小程序端
  • build 命令可以把Taro代码编译成不同端的代码,然后再对应的开发工具中查看效果

    • H5直接在浏览器中可以查看效果
    • 微信小程序需要在《微信开发工具》打开根目录下dist查看效果
    • RN应用需要参考《React Native端开发流程》

1.1.2 项目目录结构

1.2 Taro+React开发规范

  • 为了实现多端兼容,综合考虑编译速度,运行性能等因素,Taro约定了如下开发规范
    • 页面文件遵循 React组件(JSX)规范
    • 组件标签靠近小程序规范(但遵从大驼峰,并导包),详见Taro组件规范
    • 接口能力(JS API)靠近小程序规范,但需要将前缀wx替换为Taro(需要导包),详见Taro接口规范
    • 数据绑定及事件处理同React规范,同时补充了APP及页面的生命周期
    • 为了兼容多端运行,建议使用Flex布局进行开发,推荐使用px单位(750设计稿)
    • 在React中使用Taro内置组件前,必须从 @tarojs/components进行引入
    • 文档直接查看Taro的官网文档: https://docs.taro.zone/docs

1.3 webpack编译配置(config)

  • https://docs.taro.zone/docs/config

  • https://docs.taro.zone/docs/config-detail

  • 编译配置存放于项目根目录下的config目录中,包含三个文件:

    • index.js 是通用配置
    • dev.js 是项目开发时的配置
    • prod.js 是项目生产环境时的配置
  • 常用的配置

    • projectName: 项目名称
    • date: 项目创建时间
    • designWidth: 设计稿尺寸
    • sourceRoot: 项目源码目录
    • outputRoot: 项目产出目录
    • defineConstants: 定义全局的变量(DefinePlugin)
    • alias: 配置路径别名
    • h5:webpackChain: webpack配置
    • h5:devServer: 开发者服务配置

1.3.1 定义常量

// config/index.js
defineConstants: {
VERSION: "'1.0.0'"
},
// .eslintrc
"globals": {
"definePageConfig": "readonly",
"defineAppConfig": "readonly",
"VERSION": "readonly"
}
// src/pages/index/index.jsx
console.log(VERSION)

1.3.2 alias

import path from 'path'

...

alias: {
"@": path.resolve(__dirname, '..', 'src'),
},

1.4 全局配置(app.config.js)

Taro学习笔记前端阅读需 3 分钟

0. 快速链接

1. 安装Taro

  • 目前Taro仅提供一种开发方式:安装 Taro 命令行工具(Taro CLI)进行开发

  • Taro CLI 依赖于 Node.js 环境。

  • 如果Node.js环境存在,输入 npm i -g @tarojs/cli 安装, 安装好之后,输入 taro验证:

(base) jiexu:~/ $ taro                                               [12:01:03]
👽 Taro v4.1.6

2. 初始化项目

2.1 命令行初始化

  • taro init
Taro 即将创建一个新项目!
Need help? Go and open issue: https://tls.jd.com/taro-issue-helper

? 请输入项目名称! 001-docs-larning-notes
? 请输入项目介绍 will add latter
? 请选择框架 (Use arrow keys)
❯ React
PReact
Vue3
Solid
? 是否需要使用 TypeScript ? (Y/n)
? 请选择 CSS 预处理器(Sass/Less/Stylus) 无
? 请选择包管理工具 npm
? 请选择编译工具 Webpack5
? 请选择模板源 Github(最新)
✔ 拉取远程模板仓库成功!
? 请选择模板
wxcloud(云开发模板)
wxplugin
youshu(腾讯有数统计模板(https://nervjs.github.io/taro/docs/youshu))
❯ 默认模板
mobx
pwa
react-NutUI(NutUI + React 模板(https://nutui.jd.com/react/))
(Move up and down to reveal more choices)

3. 认识项目

3.1 入口组件

  • 每一个 Taro 项目都有一个入口组件和一个入口配置,我们可以在入口组件中设置全局状态/全局生命周期,一个最小化的入口组件会是这样:
// src/app.js
import React, { Component } from 'react'
import './app.css'

class App extends Component {
render() {
// this.props.children 是将要会渲染的页面
return this.props.children
}
}

// 每一个入口组件都必须导出一个 React 组件
export default App
// src/app.js
import Vue from 'vue'
import './app.css'

const App = {
render(h) {
// this.$slots.default 是将要会渲染的页面
return h('block', this.$slots.default)
},
}

export default App

每一个入口组件(例如 app.js)总是伴随一个全局配置文件(例如 app.config.js),我们可以在全局配置文件中设置页面组件的路径、全局窗口、路由等信息,一个最简单的全局配置如下:

export default {
pages: ['pages/index/index'],
}
export default {
pages: ['pages/index/index'],
}

你可能会注意到,不管是 React 还是 Vue,两者的全局配置是一样的。

这是因为在配置文件中,Taro 并不关心框架的区别,Taro CLI 会直接在编译时在 Node.js 环境直接执行全局配置的代码,并把 export default 导出的对象序列化为一个 JSON 文件。

因此,我们必须保证配置文件是在 Node.js 环境中是可以执行的,不能使用一些在 H5 环境或小程序环境才能运行的包或者代码,否则编译将会失败。

3.2 页面组件

页面组件是每一项路由将会渲染的页面,Taro 的页面默认放在 src/pages 中,每一个 Taro 项目至少有一个页面组件

一个简单的页面组件如下:

//src/pages/index/index.jsx

import { View } from '@tarojs/components'
class Index extends Component {
state = {
msg: 'Hello World!',
}

onReady() {
console.log('onReady')
}

render() {
return <View>{this.state.msg}</View>
}
}

export default Index
// src/pages/index/index.vue

<template>
<view> {{ msg }} </view>
</template>

<script>
export default {
data() {
return {
msg: 'Hello World!',
}
},
onReady() {
console.log('onReady')
},
}
</script>

与react和vue的细微差别

  • onReady 生命周期函数。这是来源于微信小程序规范的生命周期,表示组件首次渲染完毕,准备好与视图交互。Taro 在运行时将大部分小程序规范页面生命周期注入到了页面组件中,同时 React 或 Vue 自带的生命周期也是完全可以正常使用的。

  • View 组件。这是来源于 @tarojs/components 的跨平台组件。相对于我们熟悉的 div、span 元素而言,在 Taro 中我们要全部使用这样的跨平台组件进行开发。

和入口组件一样,每一个页面组件(例如 index.vue)也会有一个页面配置(例如 index.config.js),我们可以在页面配置文件中设置页面的导航栏、背景颜色等参数,一个最简单的页面配置如下:

// src/pages/index/index.config.js
export default {
navigationBarTitleText: '首页',
}

3.3 自定义组件

  • 我们先把首页写好,首页的逻辑很简单:把论坛最新的帖子展示出来。
// src/pages/index/index.jsx

import Taro from '@tarojs/taro'
import React from 'react'
import { View } from '@tarojs/components'
import { ThreadList } from '../../components/thread_list'
import api from '../../utils/api'

import './index.css'

class Index extends React.Component {
config = {
navigationBarTitleText: '首页',
}

state = {
loading: true,
threads: [],
}

async componentDidMount() {
try {
const res = await Taro.request({
url: api.getLatestTopic(),
})
this.setState({
threads: res.data,
loading: false,
})
} catch (error) {
Taro.showToast({
title: '载入远程数据错误',
})
}
}

render() {
const { loading, threads } = this.state
return (
<View className="index">
<ThreadList threads={threads} loading={loading} />
</View>
)
}
}

export default Index
// src/pages/index/index.vue

<template>
<view class="index">
<thread-list :threads="threads" :loading="loading" />
</view>
</template>

<script>
import Vue from 'vue'
import Taro from '@tarojs/taro'
import api from '../../utils/api'
import ThreadList from '../../components/thread_list.vue'
export default {
components: {
'thread-list': ThreadList,
},
data() {
return {
loading: true,
threads: [],
}
},
async created() {
try {
const res = await Taro.request({
url: api.getLatestTopic(),
})
this.loading = false
this.threads = res.data
} catch (error) {
Taro.showToast({
title: '载入远程数据错误',
})
}
},
}
</script>
  • 在我们的首页组件里,还引用了一个 ThreadList 组件,我们现在来实现它:
// src/components/thread_list.jsx

import React from 'react'
import { View, Text } from '@tarojs/components'
import { Thread } from './thread'
import { Loading } from './loading'

import './thread.css'

class ThreadList extends React.Component {
static defaultProps = {
threads: [],
loading: true,
}

render() {
const { loading, threads } = this.props

if (loading) {
return <Loading />
}

const element = threads.map((thread, index) => {
return (
<Thread
key={thread.id}
node={thread.node}
title={thread.title}
last_modified={thread.last_modified}
replies={thread.replies}
tid={thread.id}
member={thread.member}
/>
)
})

return <View className="thread-list">{element}</View>
}
}

export { ThreadList }
src/components/thread.jsx



import Taro, { eventCenter } from '@tarojs/taro'
import React from 'react'
import { View, Text, Navigator, Image } from '@tarojs/components'

import api from '../utils/api'
import { timeagoInst, Thread_DETAIL_NAVIGATE } from '../utils'

class Thread extends React.Component {
handleNavigate = () => {
const { tid, not_navi } = this.props
if (not_navi) {
return
}
eventCenter.trigger(Thread_DETAIL_NAVIGATE, this.props)
// 跳转到帖子详情
Taro.navigateTo({
url: '/pages/thread_detail/thread_detail',
})
}

render() {
const { title, member, last_modified, replies, node, not_navi } = this.props
const time = timeagoInst.format(last_modified * 1000, 'zh')
const usernameCls = `author ${not_navi ? 'bold' : ''}`

return (
<View className="thread" onClick={this.handleNavigate}>
<View className="info">
<View>
<Image src={member.avatar_large} className="avatar" />
</View>
<View className="middle">
<View className={usernameCls}>{member.username}</View>
<View className="replies">
<Text className="mr10">{time}</Text>
<Text>评论 {replies}</Text>
</View>
</View>
<View className="node">
<Text className="tag">{node.title}</Text>
</View>
</View>
<Text className="title">{title}</Text>
</View>
)
}
}

export { Thread }
// src/components/thread_list.vue

<template>
<view className="thread-list">
<loading v-if="loading" />
<thread
v-else
v-for="t in threads"
:key="t.id"
:node="t.node"
:title="t.title"
:last_modified="t.last_modified"
:replies="t.replies"
:tid="t.id"
:member="t.member"
/>
</view>
</template>

<script>
import Vue from 'vue'
import Loading from './loading.vue'
import Thread from './thread.vue'
export default {
components: {
loading: Loading,
thread: Thread,
},
props: {
threads: {
type: Array,
default: [],
},
loading: {
type: Boolean,
default: true,
},
},
}
</script>
// src/components/thread.vue

<template>
<view class="thread" @tap="handleNavigate">
<view class="info">
<view>
<image :src="member.avatar_large | url" class="avatar" />
</view>
<view class="middle">
<view :class="usernameCls"> {{member.username}} </view>
<view class="replies">
<text class="mr10">{{time}}</text>
<text>评论 {{replies}}</text>
</view>
</view>
<view class="node">
<text class="tag">{{node.title}}</text>
</view>
</view>
<text class="title">{{title}}</text>
</view>
</template>

<script>
import Vue from 'vue'
import { eventCenter } from '@tarojs/taro'
import Taro from '@tarojs/taro'
import { timeagoInst, Thread_DETAIL_NAVIGATE } from '../utils'
import './thread.css'
export default {
props: ['title', 'member', 'last_modified', 'replies', 'node', 'not_navi', 'tid'],
computed: {
time() {
return timeagoInst.format(this.last_modified * 1000, 'zh')
},
usernameCls() {
return `author ${this.not_navi ? 'bold' : ''}`
},
},
filters: {
url(val) {
return 'https:' + val
},
},
methods: {
handleNavigate() {
const { tid, not_navi } = this.$props
if (not_navi) {
return
}
eventCenter.trigger(Thread_DETAIL_NAVIGATE, this.$props)
// 跳转到帖子详情
Taro.navigateTo({
url: '/pages/thread_detail/thread_detail',
})
},
},
}
</script>

  • 这里可以发现我们把论坛帖子渲染逻辑拆成了两个组件,并放在 src/components 文件中,因为这些组件是会在其它页面中多次用到。 拆分组件的力度是完全由开发者决定的,Taro 并没有规定组件一定要放在 components 文件夹,也没有规定页面一定要放在 pages 文件夹。

  • 另外一个值得注意的点是:我们并没有使用 div/span 这样的 HTML 组件,而是使用了 View/Text 这样的跨平台组件。

3.4 路由与 Tabbar

  • src/components/thread 组件中,我们通过
Taro.navigateTo({ url: '/pages/thread_detail/thread_detail' })

跳转到帖子详情,但这个页面仍未实现,现在我们去入口文件配置一个新的页面:

// src/app.config.js

export default {
pages: ['pages/index/index', 'pages/thread_detail/thread_detail'],
}

然后在路径 src/pages/thread_detail/thread_detail 实现帖子详情页面,路由就可以跳转,我们整个流程就跑起来了:

// src/pages/thread_detail/thread_detail

import Taro from '@tarojs/taro'
import React from 'react'
import { View, RichText, Image } from '@tarojs/components'
import { Thread } from '../../components/thread'
import { Loading } from '../../components/loading'
import api from '../../utils/api'
import { timeagoInst, GlobalState } from '../../utils'

import './index.css'

function prettyHTML (str) {
const lines = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']

lines.forEach(line => {
const regex = new RegExp(`<${line}`, 'gi')

str = str.replace(regex, `<${line} class="line"`)
})

return str.replace(/<img/gi, '<img class="img"')
}

class ThreadDetail extends React.Component {
state = {
loading: true,
replies: [],
content: '',
thread: {}
} as IState

config = {
navigationBarTitleText: '话题'
}

componentWillMount () {
this.setState({
thread: GlobalState.thread
})
}

async componentDidMount () {
try {
const id = GlobalState.thread.tid
const [{ data }, { data: [ { content_rendered } ] } ] = await Promise.all([
Taro.request({
url: api.getReplies({
'topic_id': id
})
}),
Taro.request({
url: api.getTopics({
id
})
})
])
this.setState({
loading: false,
replies: data,
content: prettyHTML(content_rendered)
})
} catch (error) {
Taro.showToast({
title: '载入远程数据错误'
})
}
}

render () {
const { loading, replies, thread, content } = this.state

const replieEl = replies.map((reply, index) => {
const time = timeagoInst.format(reply.last_modified * 1000, 'zh')
return (
<View className='reply' key={reply.id}>
<Image src={reply.member.avatar_large} className='avatar' />
<View className='main'>
<View className='author'>
{reply.member.username}
</View>
<View className='time'>
{time}
</View>
<RichText nodes={reply.content} className='content' />
<View className='floor'>
{index + 1} 楼
</View>
</View>
</View>
)
})

const contentEl = loading
? <Loading />
: (
<View>
<View className='main-content'>
<RichText nodes={content} />
</View>
<View className='replies'>
{replieEl}
</View>
</View>
)

return (
<View className='detail'>
<Thread
node={thread.node}
title={thread.title}
last_modified={thread.last_modified}
replies={thread.replies}
tid={thread.id}
member={thread.member}
not_navi={true}
/>
{contentEl}
</View>
)
}
}

export default ThreadDetail


// src/pages/thread_detail/thread_detail.vue



<template>
<view class="detail">
<thread
:node="topic.node"
:title="topic.title"
:last_modified="topic.last_modified"
:replies="topic.replies"
:tid="topic.id"
:member="topic.member"
:not_navi="true"
/>
<loading v-if="loading" />
<view v-else>
<view class="main-content">
<rich-text :nodes="content | html" />
</view>
<view class="replies">
<view v-for="(reply, index) in replies" class="reply" :key="reply.id">
<image :src="reply.member.avatar_large" class="avatar" />
<view class="main">
<view class="author"> {{reply.member.username}} </view>
<view class="time"> {{reply.last_modified | time}} </view>
<rich-text :nodes="reply.content_rendered | html" class="content" />
<view class="floor"> {{index + 1}} 楼 </view>
</view>
</view>
</view>
</view>
</view>
</template>

<script>
import Vue from 'vue'
import Taro from '@tarojs/taro'
import api from '../../utils/api'
import { timeagoInst, GlobalState, IThreadProps, prettyHTML } from '../../utils'
import Thread from '../../components/thread.vue'
import Loading from '../../components/loading.vue'
import './index.css'
export default {
components: {
loading: Loading,
thread: Thread,
},
data() {
return {
topic: GlobalState.thread,
loading: true,
replies: [],
content: '',
}
},
async created() {
try {
const id = GlobalState.thread.tid
const [
{ data },
{
data: [{ content_rendered }],
},
] = await Promise.all([
Taro.request({
url: api.getReplies({
topic_id: id,
}),
}),
Taro.request({
url: api.getTopics({
id,
}),
}),
])
this.loading = false
this.replies = data
this.content = content_rendered
} catch (error) {
Taro.showToast({
title: '载入远程数据错误',
})
}
},
filters: {
time(val) {
return timeagoInst.format(val * 1000)
},
html(val) {
return prettyHTML(val)
},
},
}
</script>

到目前为止,我们已经实现了这个应用的所有逻辑,除去「节点列表」页面(在进阶指南我们会讨论这个页面组件)之外,剩下的页面都可以通过我们已经讲解过的组件或页面快速抽象完成。按照我们的计划,这个应用会有五个页面,分别是:

  1. 首页,展示最新帖子(已完成)
  2. 节点列表
  3. 热门帖子(可通过组件复用)
  4. 节点帖子 (可通过组件复用)
  5. 帖子详情 (已完成)

其中前三个页面我们可以把它们规划在 tabBar 里,tabBar 是 Taro 内置的导航栏,可以在 app.config.js 配置,配置完成之后处于的 tabBar 位置的页面会显示一个导航栏。最终我们的 app.config.js 会是这样:

// app.config.js


export default {
pages: [
'pages/index/index',
'pages/nodes/nodes',
'pages/hot/hot',
'pages/node_detail/node_detail',
'pages/thread_detail/thread_detail',
],
tabBar: {
list: [
{
iconPath: 'resource/latest.png',
selectedIconPath: 'resource/lastest_on.png',
pagePath: 'pages/index/index',
text: '最新',
},
{
iconPath: 'resource/hotest.png',
selectedIconPath: 'resource/hotest_on.png',
pagePath: 'pages/hot/hot',
text: '热门',
},
{
iconPath: 'resource/node.png',
selectedIconPath: 'resource/node_on.png',
pagePath: 'pages/nodes/nodes',
text: '节点',
},
],
color: '#000',
selectedColor: '#56abe4',
backgroundColor: '#fff',
borderStyle: 'white',
},
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'V2EX',
navigationBarTextStyle: 'black',
},
}
Taro学习笔记前端阅读需 10 分钟

下定决心还是再学一遍JS等前端知识

  • 前端技术
    • HTML:简单易学,掌握常用的标签即可
    • CSS:CSS属性规则较多,多做练习和项目
    • JavaScript:上手容易,但是精通很难 学会它只需要几分钟,掌握它需要很多年

1.1 认识编程语言

1.1.1 编程语言定义

  • 计算机语言

    • HTML是一种标记语言,CSS是一种样式语言,属于计算机语言
    • JS adds life to a web page!
  • JavaScript准确的说一门编程语言

    • 编程语言(英语:programming language),是用来定义计算机程序的形式语言。它是一种被标准化的交流技巧用来向计算机发出指令,一种能够让程序员准确地定义计算机所需要使用数据的计算机语言,并精确地定义在不同情况下所应当采取的行动
  • 编程语言具备的特点

    • 数据和数据结构
    • 指令以及流程控制
    • 引用机制和重用机制
    • 设计哲学

1.1.2 常见的编程语言

常见的编程语言

  • 比如LISP,现在仍然非常有用

    • 《黑客与画家》,人工智能
  • 早期的语言,更接近机器的思维方式

  • 近代更接近于人类的思维方式

1.2 编程语言发展历史

1.2.1 阶段一:机器语言

  • 计算机的存储单元只有0和1两种状态,因此一串代码要让计算机“读懂”,这串代码只能由数字0和1组成。

  • 像这种由数字0和1按照一定的规律组成的代码就叫机器码,也叫二进制编码

  • -定长度的机器码组成了机器指令,用这些机器指令所编写的程序就称为机器语言

  • 优点

    • 代码能被计算机直接识别,不需要经过编译解析直接对硬件产生作用
    • 程序的执行效率非常高
  • 缺点

    • 程序全是些0和1的指令代码,可读性差,还容易出错
    • 不易编写(目前没有人这样开发);

1.2.2 阶段二:汇编语言

  • 为了解决机器语言的缺陷,人们发明了另外一种语言--汇编语言,

  • 这种语言用符号来代替冗长的、难以记忆的0、1代码,(mov/push指令,经过汇编器,汇编代码再进一步转成0101)

  • 优点

    • 像机器语言一样,可以直接访问、控制计算机的各种硬件设备
    • 占用内存少,执行速度快;
  • 缺点

    • 第一,不同的机器有不同的汇编语言语法和编译器,代码缺乏可移植性 也就是说,一个程序只能在一种机器上运行,换到其他机器上可能就不能运行;
    • 第二,符号非常多、难记 即使是完成简单的功能也需要大量的汇编语言代码,很容易产生BUG,难于调试,
  • 应用场景

    • 操作系统内核,驱动程序,单片机程序

1.2.3 阶段三:高级语言

  • 好的编程语言应该是什么?自然语言

  • 而高级语言,就是接近自然语言,更符合人类的思维方式

  • 跟和人交流的方式很相似,但是大多数编程语言都是国外发明的,因为都是接近于英文的交流方式

  • 优点

    • 简单、易用、易于理解,语法和结构类似于普通英文
    • 远离对硬件的直接操作,使得一般人经过学习之后都可以编程,而不用熟悉硬件知识,
    • -个程序还可以在不同的机器上运行,具有可移植性;
  • 缺点

    • 程序不能直接被计算机识别需要经编译器翻译成二进制指令后,才能运行到计算机上,
    • 种类繁多:JavaScript、c语言、C++、C#、Java、Objective-C、Python等,

高级语言-汇编语言-机器语言

前端,需要学好的只有一门高级语言:JavaScript

1.3 JavaScript的历史

1.3.1 认识JavaScript

  • 维基百科对JavaScript的定义:

    • JavaScript(通常缩写为JS)是一种高级的、解释型的编程语言
    • JavaScript是一门基于原型、头等函数的语言,是一门多范式的语言,它支持面向对象程序设计,指令式编程,以及函数式编程;
  • 上面的定义中,我们会发现很多关键词:

    • 解释型语言?原型?头等函数?多范式?面向对象程序设计?指令式编程?函数式编程?
    • 这些改变往挂会让人不知所云,需要我们完全掌握JavaScript再来回头看,每一个词语描述的都非常准确;
  • 现在只需要知道,通俗的说法:

    • JavaScript是一门高级编程语言,是前端开发的重要组成部分!
  • HTML和CSS也是前端开发的重要组成部分,而JavaScript是前端开发的灵魂

1.3.2 JavaScript的起源

  • 1994年,网景公司(Netscape)发布了Navigator浏览器0.9版口

    • 这是历史上第一个比较成熟的网络浏览器,轰动一时。
    • 但是,这个版本的浏览器只能用来浏览,不具备与访问者互动的能力。
    • 网景公司急需一种网页脚本语言,使得浏览器可以与网页互动,
  • 网景公司当时想要选择一种语言来嵌入到浏览器中:

    • 采用现有的语言,比如Perl、Python、Tel、Scheme等等,允许它们直接嵌入网页;
    • 1995年网景公司招募了程序员Brendan Eich,希望将Scheme语言作为网页脚本语言的可能性;
  • 就在这时,发生了另外一件大事:1995年Sun公司将0ak语改名为Java,正式向市场推出;

    • Java推出之后立马在市场上引起了轰动,Java当初有一个口号:"write once run anywhere"
    • 网景公司动了心,决定与Sun公司结成联盟,希望将Java嵌入到网页中来运行;
    • Brendan Eich本人非常热衷于Scheme,但是管理层那个时候有点倾向于Java,希望可以简化Java来适应网页脚本的需求
  • 但是Brendan Eich对此并不感兴趣,他用10天时间设计出来了JavaScript;

    • 最初这门语言的名字是Mocha(摩卡)
    • 在Navigator2.0 beta版本更名为LiveScript,
    • 在Navigator2.0 beta 3版本正式重命名为JavaScript,当时是为了给这门语言搭上Java这个热词;
  • 当然10天设计出来语言足够说明Brendan Eich是天才,但是这门语言当时更像是一个多种语言的大杂烩:

    • 借鉴c语言的基本语法;
    • 借鉴Java语言的数据类型和内存管理;
    • 借鉴Scheme语言,将函数提升到"第一等公民"(first class)的地位;
    • 借鉴Self语言,使用基于原型(prototype)的继承机制。
  • Brendan Eich曾经这样描述过JavaScript:

    • 与其说我爱Javascript,不如说我恨它,它是C语言和Self语言一夜情的产物口
    • 十八世纪英国文学家约翰逊博士说得好:"它的优秀之处并非原创,它的原创之处并不优秀 (the part that is good is not original, and the part that is original is not good.)
  • 微软公司于1995年首次推出InternetExplorer, 从而引发了与Netscape的浏览器大战。

    • 微软对Netscape Navigator解释器进行了逆向工程,以与处于市场领导地位的网景产品同台竞争; 创建寸JScript,
    • 这个时候对于开发者来说是一场噩耗:因为需要针对不同的浏览器进行不同的适配; 1996年11月,网景正式向ECMA(欧洲计算机制造商协会)提交语言标准。
    • 1997年6月,ECMA以JavaScript语言为基础制定了ECMAScript标准规范ECMA-262口 ECMA-262是一份标准,定义了ECMAScript;
    • JavaScript成为了ECMAScript最著名的实现之除此之外,ActionScript和JScript也都是ECMAScript规范的实现语言;
所以说,ECMAScript是一种规范,而JavaScript是这种规范的一种实现。

1.4 JavaScript的分类

1.4.1 JavaScript的组成

  • ECMAScript是JavaScript的标准,描述了该语言的语法和基本对象。

    • JavaScript是ECMAScript的语言层面的实现;
    • 因为除了语言规范之外,JavaScript还需要对页面和浏览器进行各种操作
    • 除了基本实现之外,还包括DOM操作和BOM操作;
  • JavaScript的组成

    • ECMAScript 定义语言规范
    • DOM 用于操作文档的API
    • BOM 用于操作浏览器的API
  • 目前我们会针对性的学习ECMAScript,也就是语言层面的内容,特别是ES5之前的语法

课程学习顺序

ECMA-历史

1.5 JavaScript运行引擎

1.5.1 JavaScript由谁来运行

  • 我们经常会说:不同的浏览器有不同的内核组成

    • Gecko:早期被Netscape和Mozila Firefox浏览器浏览器使用
    • Trident:微软开发,被IE4~IE11浏览器使用,但是Edge浏览器已经转向Blink
    • Webkit:苹果基于KHTML开发、开源的,用于Safari,Google Chrome之前也在使用;
    • Blink:是Webkit的一个分支,Google开发,目前应用于Google Chrome、Edge、Opera等;
    • 等等.
  • 事实上,我们经常说的浏览器内核指的是浏览器的排版引擎:

    • 排版引擎(layout engine),也称为浏览器引擎(browserengine)
    • 页面渲染引擎(rendering engine)或样版引擎
  • JavaScript代码由谁来执行?

    • JavaScript引擎

1.5.2 认识JavaScript引擎

  • 为什么需要JavaScript引擎呢?
    • 我们前面说过,高级的编程语言都是需要转成最终的机器指令来执行的;
    • 事实上我们编写的JavaScript无论你交给浏览器或者Node执行,最后都是需要被CPU执行的;
    • 但是CPU只认识自己的指令集,实际上是机器语言,才能被CPU所执行,
    • 所以我们需要JavaScript引擎帮助我们将JavaScript代码翻译成CPU指令来执行;

比较常见的JavaScript引擎有哪些呢?

  • SpiderMonkey:第一款JavaScript引擎,由Brendan Eich开发(也就是JavaScript作者)
  • Chakra:微软开发,用于IE浏览器
  • JavaScriptCore: WebKit中的JavaScript引擎,Apple公司开发;
    • 手机端比较多,
    • IOS-> UIWebView
    • 小程序
  • V8:Google开发的强大JavaScript引擎,也帮助Chrome从众多浏览器中脱颖而出;
  • 等等...

1.5.3 浏览器内核和JS引擎的关系

  • 这里我们先以WebKit为例,WebKit事实上由两部分组成的:

    • WebCore:负责HTML解析、布局、渲染等等相关的工作
    • JavaScriptCore:解析、执行JavaScript代码:
  • 小程序中也是这样的划分

    • 在小程序中编写的JavaScript代码就是被JSCore执行的;

WebKit浏览器内核和JS引擎的关系

小程序中的JS引擎

1.6 JavaScript应用场景

1.6.1 著名的Atwood定律

  • Stack Overflow的创立者之一的 Jeff Atwood 在2007年提出了著名的 Atwood定律:
    • Any application that can be written in JavaScript, will eventually be written in JavaScript.
    • 任何可以使用JavaScript来实现的应用都最终都会使用JavaScript实现

1.6.2 JS应用越来越广泛

JavaScript应用场景

2. JavaScript基础

3. 变量与数据类型

3.1 认识JavaScript变量

3.2 变量的定义,规范等

3.3 数据类型和typeof

3.4 常见的数据类型

3.5 数据类型的转换

JavaScript学习笔记前端阅读需 10 分钟

下定决心还是再学一遍JS等前端知识

1. JavaScript编写方式

1.1 编写在HTML内部

<a href="#" onclick="alert('百度一下')">百度-下</a>

<a href="alert('百度一下')">百度-下</a>

1.2 编写在Script元素内

<a class="google" href="#">Google一下</a>

<script>
var google = document.querySelector(".google");
google.onclick = function() {
alert("google");
}
</script>

1.3 独立的js文件

  • 通过script的src属性来引入外部文件
  • bing.js
var bing = document.querySelector(".bing");
bing.onclick = function() {
alert("bing");
}
  • .html
<script src="./bing.js"></script>

2. noscript元素的使用

<noscript>
您的浏览器不支持JavaScript
</noscript>

3. JavaScript注意事项

注意一: script元素不能写成单标签 口在外联式引用js文件时,script标签中不可以写JavaScript代码,并且script标签不能写成单标签 口即不能写成; 注意二: 省略type属性 口 在以前的代码中,

<script>标签中会使用 type="text/javascript"口 现在可不写这个代码了,因为JavaScript 是所有现代浏览器以及 HTML5 中的默认脚本语言</script>

注意三: 加载顺序 口 作为HTML文档内容的一部分,JavaScript默认遵循HTML文档的加载顺序,即自上而下的加载顺序;口 推荐将JavaScript代码和编写位置放在body子元素的最后一行 注意四: JavaScript代码严格区分大小写 口 HTML元素和CSS属性不区分大小写,但是在JavaScript中严格区分大小写后续补充:script元素还有defer、async属性,我们后续再详细讲解

4. JavaScript交互方式

4.1 JavaScript交互方式

  • JavaScript有如下和用户交互的手段

  • 最常用的是console.log

  • 交互方法

    • alert
      • 接受一个参数,弹窗查看
    • console.log
      • 接受多个参数,在浏览器控制台查看
    • document.write
      • 接受多个字符串,在浏览器页面查看
    • prompt
      • 接受一个参数,在浏览器接受用户输入

4.2 Chrome的调试工具

  • 使用Console来查看JavaScript的一些内容

  • 补充

    • 1.如果在代码中出现了错误,那么可以在console中显示错误
    • 2.console中有个>标志,它表示控制台的命令行
      • 在命令行中我们可以直接编写JavaScript代码,按下enter会执行代码;
      • 如果希望编写多行代码,可以按下shift+enter来进行换行编写;
    • 3.在后续我们还会学习如何通过debug方式来调试、查看代码的执行流程

5. JavaScript语句和分号

  • 语句是向浏览器发出的指令,通常表达一个操作或者行为(Action)
    • 语句英文是Statements;
    • 比如我们前面编写的每一行代码都是一个语句,用于告知浏览器一条执行的命令

alert("Hello World");

  • 通常每条语句的后面我们会添加一个分号,表示语句的结束:

    • 分号的英文是semicolon
    • 当存在换行符(line break)时,在大多数情况下可以省略分号
    • JavaScript 将换行符理解成"隐式"的分号
    • 这也被称之为自动插入分号(an automatic semicolon)
  • 推荐

    • 前期在对Javascript语法不熟悉的情况推荐添加分号
    • 后期对JavaScript语法熟练的情况下,任意!

6. JavaScript注释方式

  • 单行注释

    • // xxx
  • 多行注释

    /*
    ...
    */
  • 文档注释

    • 使用插件: jsDoc

    /**

    • 和某人打招呼的函数
    • @param {string} name 姓名
    • @param {number} age 年龄 function sayHello(name, age)

    sayHello("jie", 28) */

7. VSCode 插件和配置

  • 推荐一个VSCode的插件:(个人经常使用的)
    • ES7+ React/Redux/React-Native snippets
    • 这个插件是在react开发中会使用到的,但是我经常用到它里面的打印语句,

另外再推荐一个插件:

  • Bracket Pair Colorizer2,但是该插件已经不再推荐使用了

    • 因为VSCode已经内置了该功能,我们可以直接通过VSCode的配置来达到插件的效果;
    • 如何配置呢?
      • 右上角打开设置 -> 出现配置文件,放到最下面的位置即可
      • 文件 -> 首选项 -> 设置 ->
    "editor.bracketPairColorization.enabled": true,
    editor.guides.bracketPairs":"active"

  • 比如敲console.log(),

    • 可以直接打log,会出来console.log()
    • 另一种方式是,敲clg,使用的插件是react插件

8. 变量与数据类型

8.1 认识JavaScript变量

8.1.1 程序中的变量

  • 在我们平时开发中,使用最多的并不是固定的数据,而是会变换的数据:
    • 比如购物车商品的数量、价格的计算等等
    • 比如一首歌曲播放的时间、进度条、歌词的展示等等
    • 比如微信聊天中消息条数、时间、语音的长度、头像、名称等等;
    • 比如游戏中技能的冷却时间、血量、蓝量、buff时间、金币的数量等等;

8.1.2 变化数据的记录-变量

  • 如果我们希望记录某一个之后会变量的数据,在JavaScript中我们可以定义一个 变量

    • 一个变量,就是一个用于存放数值的容器
    • 这个数值可能是一个用于计算的数字,或者是一个句子中的字符串,或者其他任意的数据
    • 变量的独特之处在于它存放的数值是可以改变的;
  • 我们可以把变量想象成一个盒子,盒子里面装着我们的数据,我们需要给盒子进行一个特性的名称。

    • 例如,变量 message 可以被想象成一个标有"message"的盒子,盒子里面的值为"Hello!"
    • 并且,这个盒子的值,我们想改变多少次,就可以改变多少次;

8.2 变量的定义,规范等

8.2.1 变量的命名格式

  • 在JavaScript中如何命名一个变量呢?包含两部分:

    • 变量的声明:在JavaScript中声明一个变量使用var关键字(variable单词的缩写)(后续学习ES6还有let、const声明方式)
    • 变量的赋值:使用=给变量进行赋值;
  • 也可以分开操作

    var name;
    name = "Jie";
  • 同时声明多个变量

    var name, age, height;
    name = "Jie";
    age = 18;
    height = 188;

8.2.2 变量的命名规范

变量命名规范:建议遵守

  • 多个单词使用驼峰标识
  • 赋值 =两边都加上一个空格
  • 一条语句结束后加上分号;也有很多人的习惯是不加!
  • 变量应该做到见名知意

8.2.3 练习

  • 定义两个变量保存两个数字,对两个变量中的数字进行交换
    • 方法一:借助第三个变量
    • 方法二:不借助第三个变量
      num1 = num1 + num2
      num2 = num1 - num2
      num1 = num1 - num2

8.2.3 注意

  • 如果一个变量没被声明,就直接使用,会报错

  • 如果一个变量声明了,但是没被赋值,默认值是 undefined

  • 如果没有使用var声明变量也可以,但是不推荐,(事实上会被添加到window对象上)

8.3 数据类型和typeof

8.3.1 JavaScript的数据类型

  • JavaScript 中的值都具有特定的类型。

    • 例如,字符串或数字。
    • 我们可以将值赋值给一个变量,那么这个变量就具备了特定的类型
    • 一个变量可以在前一刻是个字符串,下一刻就存储一个数字,
    • 允许这种操作的编程语言,例如JavaScript,被称为"动态类型"(dynamically typed)的编程语言;
  • 在JavaScript 中有8种基本的数据类型(7 种原始类型和1种复杂类型)

    • Number
    • String
    • Boolean
    • Undefined
    • Null
    • Object
    • Bigint(后续了解)
    • Symbol(后续了解)

8.3.2 typeof操作符

  • 因为 ECMAScript 的类型系统是松散的,所以需要一种手段来确定任意变量的数据类型

    • typeof 操作符就是为此而生的。
  • 对一个值使用 typeof 操作符会返回下列字符串之一:

    • "undefined"表示值未定义;
    • "boolean"表示值为布尔值;
    • "string"表示值为字符串;
    • "number"表示值为数值;
    • "object"表示值为对象(而不是函数)或 null;
    • "function"表示值为函数;
    • "symbol"表示值为符号
  • typeof()的用法:

    • 你可能还会遇到另一种语法:typeof(x),它与 typeof x 相同
      • 类似 var result = (2+3)*4;, ()是将 2+3作为一个整体
    • typeof是一个操作符,并非是一个函数,()只是将后续的内容当做一个整体而已

8.4 常见的数据类型

8.5 数据类型的转换

JavaScript学习笔记前端阅读需 8 分钟

下定决心还是再学一遍CSS等前端知识

1. 认识Flex布局和Flex布局的由来

1.1 认识Flex box

  • Flexbox翻译为弹性盒子
    • 弹性盒子是一种用于按行或者按列布局元素的一维布局方法
    • 元素可以膨胀以填充额外的空间,收缩以适应更小的空间
    • 通畅我们使用Flexbox来进行布局的方案称之为flex布局(flex layout)
  • flex布局是目前web开发中使用最多的布局方案
    • flex布局(Flexible布局,弹性布局)
    • 目前特别在移动端可以说已经完全普及
    • 在PC端也几乎已经完全普及和使用,只有非常少数的网站依然在用浮动来布局
  • 为什么需要flex布局
    • 长久以来,CSS布局中唯一可靠且跨浏览器兼容的布局工具只有floats和positioning
    • 但是这两种方法本身存在很大的局限性,使用他们是无奈之举

1.2 原先布局存在的痛点

  • 举例
    • 比如在父内容里面垂直居中一个块内容
      • "44 years ago we put a man on the moon, but we still can't vertically center things in CSS." -- by Juozas Kaziukenas, 2013-07-21
    • 使容器的所有子项等分可用宽度/高度,而不管有多少宽度/高度可用
    • 使多列布局中的所有列采用相同的高度,即使他们包含的内容量不同

1.3 Flex布局的出现

  • 所以长久以来,大家非常期待一种真正可以用于对元素布局的方案:于是Flex布局出现了

    • "Nature and nature's laws lay hid in night; God said "Let Newton be" and was light." -- 牛顿的墓志铭
  • 如果担心其兼容性问题

    • 可以在CanIuse查询具体的兼容性

2. 两个非常重要的概念

  • 开启了flex布局的元素叫 flex container
  • flex container里面的直接子元素叫做 flex item

2.1 container

  • 设置display属性为flex或者inline-flex可以成为flex container
    • flex:flex container以block-level形式存在
    • inline-flex:flex container以inline-level形式存在

2.2 flex item

  • 当flex container中的子元素变成了flex item的时候,具备以下特点
    • flex item的布局将受flex container属性的设置来进行控制和布局
    • flex item不再严格区分块级元素和行内级元素
    • flex item默认情况下是包裹内容的,但是可以设置宽度和高度

3. Flex布局的模型,坐标轴,主轴和交叉轴

Flex布局的模型

  • main axis
  • cross axis

4. Flex相关的属性

4.1 应用在flex container上的CSS属性

4.1.1 flex-flow

4.1.2 flex-direction

  • 决定main axis的方向
    • row 默认值
    • row-reverse
    • column
    • column-reverse

4.1.3 flex-wrap

  • nowrap: 默认,单行
  • wrap: 多行
  • wrap-reverse: 多行,对比wrap,cross start与 cross end相反

4.1.4 justify-content

4.1.5 align-items

4.1.6 align-content

4.1.7 flex-flow

  • 是flex-direction和flex-wrap的简写属性
    • 顺序随便,并且都可以省略

4.1.8 justify-content

justify-content

  • flex-start: 默认值,与main start 对其
  • flex-end:与main end对其
  • center 居中对其
  • space-between:
    • flex items之间的距离相等
    • 与main start,main end两端对齐
  • space-arount:
    • flex items之间的距离相等
    • flex items与main start,main end之间的距离是flex items之间距离的一半
  • space-evenly:
    • flex items之间的距离相等
    • flex items与main start,main end之间的距离等于flex items之间距离

4.1.9 align-items

align-items

  • align-items 决定了flex items在cross axis上的对齐方式
    • normal: 在弹性布局中,效果和stretch一样
    • stretch:当flex items在cross axis方向的size为auto时,会自动拉伸至填充flex container
    • flex-start: 与cross start对齐
    • flex-end:与cross end对齐
    • center: 居中对齐
    • baseline: 与基准线对齐

4.1.10 align-content

align content

  • 决定了多行flex items在cross axis上的对齐方式,用法与justify-content类似
    • stretch 默认值:与align-items的stretch类似
    • flex-start
    • flex-end
    • center
    • space-between
    • space-around
    • space-evenly

4.2 应用在flex items 上的CSS属性

4.2.1 flex-grow

  • 决定了flex items如何扩展(拉伸/成长)
    • 默认值是0,可以设置任意非负数字,
    • 当flex container在main axis方向上有剩余 size时,flex-grow属性才会有效
  • 如果所有 flex items的flex-grow总和sum超过1,每个flex item扩展的size为
    • flex container 的剩余size * flex-grow / sum
  • flex items扩展后的最终size不能超过max-width/max-height

4.2.2 flex-basis

  • 用来设置flex items在main axis方向上的base size
    • auto 默认值
    • 具体的宽度数值
  • 决定flex items最终base size的因素,优先级从高到低
    • max-width,max-height,min-width,min-height
    • flex-basis
    • width,height
    • 内容本身的size

4.2.3 flex-shrink

4.2.4 order

  • order越小,越排在前面
  • 可以设置任意整数,默认值是0

4.2.5 align-self

  • 覆盖flex container设置的align-items
    • auto

4.2.6 flex

-flex是flex-grow,flex-shrink,flex-basis的简写,可以指定1个,2个或者3个值

  • 单值语法:值必须为以下其中之一 -一个无单位:会被当作flex-grow

    • 一个有效的宽度值:会被当作flex-basis的值
    • 关键字none,auto或者initial -双值语法
    • 第一个值必须为一个无单位数,并且会被当作flex-grow的值
    • 第二个必须为以下之一:
      • 一个无单位数:会被当作flex-shrink的值
      • 一个有效的宽度值:会被当作flex-basis的值
  • 三值语法

    • 第一个必须无单位: flex-grow
    • 第二个必须无单位: flex-shrink
    • 第三个必须为一个有效的宽度值:flex-basis
  • 添加span的个数是列数减2

CSS学习笔记前端定位Flex阅读需 5 分钟

1. CSS相关

  • "子绝父相", "子绝父固"都在什么情况下使用,举一个例子
  • 什么是标准流
    • position的什么属性会脱离标准流
  • 居中问题
    • margin如何居中
    • text-align: center
    • 绝对定位元素如何水平,垂直居中
前端阅读需 1 分钟

下定决心还是再学一遍CSS等前端知识

Day08

1. border图形

  • border-right-color

  • 旋转

    • transform: rotate(90deg);
    • transform-origin: center/25%; 旋转中心点
  • https://css-tricks.com/the-shapes-of-css

2. Web网络字体

  • 之前通过font-family设置字体
    • 我们需要提供一个或多个字体种类名称,浏览器会在列表中搜寻,直到找到它所运行的系统上可用的字体
    • 这样的方式完全没有问题,但是对于传统的web开发人员来说,字体选择是有限的
    • 这就是所谓的web-safe字体
    • 并且这种默认可选的字体并不能进行一些定制化的需求

2.1 web fonts 的工作原理

  • 首先,需要通过一些渠道获取到希望使用的字体

    • 对于某些收费的字体,需要获取到对应的授权
    • 对于某些公司定制的字体,需要设计人员来设计
    • 对于某些免费的字体,需要获取到对应的字体文件
  • 其次,在我们的CSS代码当中使用该字体(重要)

    • 具体看后面的操作流程
  • 最后,在部署静态资源的时候,将HTML/CSS/JavaScript/Font一起部署在静态服务器中

  • 用户的角度

    • 浏览一个网页的时候,因为代码中有引入字体文件,字体文件会被一起下载下来
    • 浏览器会根据使用的字体在下载的字体文件中查找,解析,使用对应的字体
    • 在浏览器中使用对应的字体显示内容

image-20250506123624288

image-20250506124626803

image-20250506125329997

  • 流媒体

    • 封装格式

    • 编码格式

3. Web字体图标

4. CSS精灵图

image-20250506194729828

spritecow.com

5. cursor属性

下定决心还是再学一遍CSS等前端知识

1. 结构伪类

1.1 nth-child

  • 奇数
    • nth-child(2n+1)
  • 偶数
    • nth-child(2n)
  • 前几个
    • nth-child(-n+5)

1.2 nth-last-child

  • nth-last-child(1)
    • 倒数第一个
  • nth-last-child(-n+2)
    • 最后2个

1.3 nth-of-type

  • nth-child类似,但是这个计数的时候只计算同种类的元素

1.4 nth-last-of-type

1.5 其他

  • :first-child
  • :last-child
  • :first-of-type
  • :last-of-type
  • :only-child
  • :only-of-type
  • :root
  • :empty
    • 里面完全空白的元素

1.6 否定伪类

  • :not(), 格式是:not(x)
    • x是简单选择器
CSS学习笔记前端阅读需 1 分钟

下定决心还是再学一遍CSS等前端知识

1. 列表元素

1.1 列表的实现方式

  • 方案一:使用div
  • 方案二:使用列表元素,
  • 事实上现在很多网站对于列表元素没有很强烈的偏好,更加不拘一格,按照自己的风格来布局
    • 原因是列表元素默认的CSS样式,让他用起来不是很方便
    • 比如列表元素往往有很多的限制,ul/ol中智能存放li,li再存放其他元素,默认样式等
    • 虽然我们可以通过重置来解决,但是我们更喜欢自由的div
  • HTML提供了3组常用的展示列表的元素
    • 有序列表:ol, li
    • 无序列表:ul, li
    • 定义列表:dl, dt, dd

2. 表格元素

  • 在网页中,对于某些内容的展示使用表格元素更为合适和方便

  • 常见元素

    • table
    • tr
    • td
    • 后增加的元素
      • thead
        • td->th
      • tbody
      • tfoot
      • caption
  • 其他已经不推荐用了

    • table元素应该使用CSS制定样式
    • 设置margin-left, margin-right为auto,来实现类似于align属性的效果
  • 案例

    • border-collapse
      • collapse折叠
  • 单元格合并

    • 跨列合并:
      • colspan
      • 在最左边的单元格使用,并省略掉合并的td
    • 跨行合并
      • rowspan
      • 在最上面的单元格使用,并省略掉合并的td
  • 案例:

    • 快捷写法:tr*12>td{数学}*6
    • 技巧
      • table tr:nth-child(-n + 2){} :n的取值,0和整数

image-20250504193314647

3. 表单元素

  • 和用户交互的重要方式之一
  • 常见的表单元素
    • form
      • 表单,一般情况下,其他表单相关的元素都是他的后代
    • input
      • 单行文本输入框,单选框,复选框,按钮
    • textarea
      • 多行文本框
    • select,option
      • 下拉选择框
    • button
      • 按钮
    • label
      • 表单元素的标题

3.1 input

  • input
    • 是一个行内替换元素
    • type
      • text
      • password
      • ratio
      • checkbox
      • button
      • reset
      • submit
      • file
      • readonly
      • disabled
      • checked
        • 默认选中,只有当type为ratio或checkbox的时候可以用
      • autofocus
      • name
      • value
      • time
      • date

3.1.1 布尔属性(boolean attributes)

  • 常见的有
    • disabled, checked, readonly, multiple, autofocus, selected
  • 布尔属性可以没有属性值,写上属性名就代表使用这个属性

3.1.2 表单按钮

  • 按钮
    • button
    • reset
    • Submit

3.1.3 input和label的关系

  • label可以展示会input的标题
  • label可以跟某个input绑定,点击某个label就可以激活对应的input变成选中
<label for="username">
用户:
</label>
<input id="username" type="text"/>
<label for="username">
用户:
<input id="username" type="text"/>
</label>

3.1.4 ratio

  • 在类型为radio的input中,如果name一样,那么两个radio就会互斥
<label for="male">
<input id="male" type="radio" name="sex" value="male">
</label>

<label for="female">
<input id="female" type="radio" name="sex" value="female">
</label>

3.1.5 checkbox

<label for="basketball">
<input id="basketball" type="checkbox" name="hobby" value="basketball">篮球
</label>

<label for="football">
<input id="football" type="checkbox" name="hobby" value="football">足球
</label>

3.2 form常见的属性

4. Emmet语法

4.1 认识Emmet语法

  • 前身为(Zen Coding) 是一个能大幅度提高前端开发效率的一个工具

    • vscode内置了Emmet语法,在后缀为.html/.css中输入缩写后按tab/Enter键即可自动生成相应的代码
  • 举例

    • ! == html:5
  • >(子代)和+兄弟

4.2 HTML Emmet

4.3 CSS Emmet

CSS学习笔记前端阅读需 3 分钟

下定决心还是再学一遍CSS等前端知识

1. 盒子模型-margin

1.1 margin 基本使用

换行符会造成两个元素之间有间距

暂时可以通过去除(后面介绍通过浮动,flex布局去除)

body {
font-size: 0;
}

依次尝试:

  • margin-top
  • margin-bottom
  • margin-right
  • margin-left
  • margin 全写,以及缩写属性

1.2. padding 和 margin对比

  • 大box包含小box,如果设置大box的padding,会让大box撑开
    • box-sizing: boder-box;
  • 设置小box的margin
    • 好处:不用设置boder-box,
    • 坏处: 但是对于margin-top会让大box也往下跑
      • 因为做了一个传递,把margin传递给了父元素
      • 解决办法,在父元素设置: overflow: auto;,不是最好的方式,后面讲
  • 补充
    • margin用来设置元素和元素之间的距离(一般是兄弟元素)
    • padding

1.3. margin上下传递问题

  • 左右不会传递

  • margin-top传递

    • 如果块级元素的顶部线和父元素的顶部线重叠,那么这个块级元素的margin-top值会传递给父元素
  • margin-bottom传递

    • 如果块级元素的底部线和父元素的底部线重叠,并且父元素的高度是auto,那么这个块级元素的margin-bottom值会传递给父元素
  • 如何防止出现传递问题?

    • 给父元素设置padding-top padding-bottom
    • 给父元素设置border
    • 触发BFC(Block Formatting Context)(块级格式上下文):设置overflow为auto
  • 建议:

    • margin一般用来设置兄弟元素之间的间距
    • padding一般用来设置父子元素之间的间距

1.4. 上下margin的折叠

  • 垂直方向上相邻2个margin(margin-top, margin-bottom)有可能合并为一个margin,这种现象叫做collapse(折叠)

  • 水平方向上的margin(margin-left, margin-right)永远不会折叠

  • 折叠后最终值的计算规则

    • 两个值比较,取较大的值
  • 如何防止margin折叠

    • 只设置其中一个元素的margin
  • 兄弟块级元素之间margin的折叠

image-20250502104448615

  • 父子块级元素之间margin的折叠

image-20250502104730263

1.5. 块级元素的水平居中-margin-auto

  • 浏览器默认会给body设置margin: 8px
  • 块级元素 block box
    • block box width = width + padding + border + margin
    • 但是默认margin-left是0
    • margin-right也是0
    • 但是浏览器优先展示width,然后再把剩余的空间设给right
  • 如果希望居中,则把margin-leftmargin-right都设置为auto
  • 点评
    • 这种方式不太好,用flex布局则是更好
    • 比如float浮动也不应该用来做布局

2.盒子模型-外轮廓-outline

  • outline表示元素的外轮廓
    • 不占用空间
    • 默认显示在border的外面
  • outline相关属性
    • outline-width
    • outline-style
    • outline-color
    • Outline: outline-width, outline-style, outline-color

3.盒子模型-阴影-box-shadow

  • box-shadow属性可以设置一个或者多个阴影

    • 每个阴影用shadow表示
    • 多个阴影之间用逗号隔开,从前到后叠加
  • 常见格式

    • none | <shadow>#
    • <shadow> = inset? && <length>{2, 4} && <color>?
    • 第一个length: offset-x,水平方向的偏移,正数往向右
    • 第二个length: offset-y,水平方向的偏移,正数往向下
    • 第3个length:blur-radius, 模糊半径
    • 第4个length:spread-radius, 延伸半径
    • color: 阴影的颜色,如果没有设置,就跟随color属性的颜色
    • inset: 外框阴影变成内框阴影
  • 坐标轴

  • blur:阴影的模糊度

  • 在线网站

4.盒子模型-文字阴影-text-shadow

5. 行内非替换元素的注意事项

  • span/a/strong/i
    • width,height不生效
    • padding, border, margin,上下可以撑大,但是不占空间

6. 盒子模型-盒子尺寸计算-box-sizing

  • 背景色有没有设置到border下面(有设置)
  • 前景色会在border没有设置颜色的情况下,显示出来color颜色
.box {
width: 100px;
height: 100px;
background-color: #f00;
color: orange;
padding: 30px;
border: 10px solid;
}
  • box-sizing用来设置盒子模型中宽高的行为
  • content-box
    • padding, border都布置在width,height外边
  • border-box
    • padding, border都布置在width,height里面

image-20250502153041620

image-20250502153105022

image-20250502153638044

7. 案例

image-20250502152032982

image-20250502152047429

image-20250502152055214

  • 灰色背景:#f5f5f5

  • 单行显示省略号

white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
CSS学习笔记前端阅读需 4 分钟

下定决心还是再学一遍 CSS 等前端知识

1. background

1.1 background-image

  • 用于设置元素的背景图片
    • 会盖在(不是覆盖)background-color 的上面
  • 如果设置了多张图片
    • 设置的第一张图片将显示在最上面,其他图片按顺序层叠在下面
  • 如果设置了背景图片后,元素没有具体的宽高,背景图片是不会显示出来的

1.2 background-repeat

1.3 background-size

  • auto: 默认值,以背景图本身大小显示
  • cover:缩放背景图,以完全覆盖铺满元素,可能背景图片部分看不见
  • contain:
  • <percentage>
  • Length

1.4 background-position

  • 用于设置背景图片在水平,垂直方向上的具体位置
    • 可以设置具体的数值,比如 20px 30px
    • 水平方向还可以设值:left, center, right
    • 垂直方向还可以设值: top, center, bottom
    • 如果只设置了一个方向,另一个方向默认是 center

1.5 background- attachment

  • 决定背景图像的位置是在视口内固定,或者随着包含它的区块滚动
  • 可以设置以下三个值
    • scroll:表示背景相对于元素本身固定,而不是随着它的内容滚动
    • local:表示背景相对于元素的内容固定,如果一个元素拥有滚动机制,背景将会随着元素的内容滚动
    • fixed

1.6 缩写属性

1.7 background-image vs. img

imgbackground-image
性质HTML 元素CSS 样式
图片是否占用空间
浏览器右键直接查看地址
支持 CSS Sprite(精灵图)
更有可能被搜索引擎收录✅(结合 alt 属性)
CSS学习笔记前端阅读需 2 分钟