当前位置: 首页 > news >正文

React【Day1】

B站视频链接

一、React介绍

React由Meta公司开发,是一个用于 构建Web和原生交互界面的库
在这里插入图片描述

React的优势

相较于传统基于DOM开发的优势

  1. 组件化的开发方式
  2. 不错的性能

相较于其它前端框架的优势

  1. 丰富的生态
  2. 跨平台支持

React的市场情况

全球最流行,大厂必备

二、开发环境创建

create-react-app是一个快速创建React开发环境的工具,底层由Webpack构件,封装了配置细节,开箱即用

执行命令:npx create-react-app 项目名

npx create-react-app react-basic

启动命令: npm start

npm start  

或者是npm run start ,run 可以省略

  1. npx - Node.js工具命令,查找并执行后续的包命令
  2. create-react-app - 核心包(固定写法),用于创建React项目
  3. react-basic React项目的名称(可以自定义)
    :::warning
    创建React项目的更多方式
    https://zh-hans.react.dev/learn/start-a-new-react-project
    :::

核心依赖和核心命令:
在这里插入图片描述

三、文件介绍

在新手阶段删除多余的文件,只保留App.js和index.js
在这里插入图片描述1. index.js
是整个项目的入口,从这里开始运行
保留基础代码:

// react 必要的2个核心包
import React from "react";
import ReactDOM from "react-dom/client";// 导入项目根组件
import App from "./App";// 把APP根组件渲染到id为root的dom节点上
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);

App.js

// 项目的跟组件
// APP.js被引入到index.js ,被index.js渲染到public/index.html(root)
function App() {return <div className="App">删除多余的东西了</div>;
}export default App;

四、JSX基础

什么是JSX

概念:JSX是JavaScript和XMl(HTML)的缩写,表示在JS代码中编写HTML模版结构,它是React中构建UI的方式

const message = 'this is message'function App(){return (<div><h1>this is title</h1>{message}</div>)
}

优势:

  1. HTML的声明式模版写法
  2. JavaScript的可编程能力

JSX的本质

JSX并不是标准的JS语法,它是 JS的语法扩展,浏览器本身不能识别,需要通过解析工具做解析之后才能在浏览器中使用

在这里插入图片描述

JSX高频场景-JS表达式

在JSX中可以通过 大括号语法{} 识别JavaScript中的表达式,比如常见的变量、函数调用、方法调用等等

  1. 使用引号传递字符串
  2. 使用JS变量
  3. 函数调用和方法调用
  4. 使用JavaScript对象
    :::warning
    注意:if语句、switch语句、变量声明不属于表达式,不能出现在{}中,仅支持表达式
    :::
const message = 'this is message'function getAge(){return 18
}function App(){return (<div><h1>this is title</h1>{/* 字符串识别 */}{'this is str'}{/* 变量识别 */}{message}{/* 变量识别 */}{message}{/* 函数调用 渲染为函数的返回值 */}{getAge()}{/* 方法调用 */}{new moment(Date().getDate).format("YYYY-MM-DD")}{/* 使用js对象 */}<div style={{ color: "red" }}></div>{/* 里面的花括号是对象结构,外层花括号是识别表达式的语法 */}</div>)
}

JSX高频场景-列表渲染

在JSX中可以使用原生js种的map方法 实现列表渲染
注意要加上key

const list = [{id:1001, name:'Vue'},{id:1002, name: 'React'},{id:1003, name: 'Angular'}
]function App(){return (<ul>{list.map(item=><li key={item.id}>{item}</li>)}</ul>)
}

JSX高频场景-条件渲染

在这里插入图片描述

在React中,可以通过逻辑与运算符&&、三元表达式(?😃 实现基础的条件渲染

&& 是短路与,只要第一个操作数是假,后面的就不会被执行
如果只控制一个元素的显示和隐藏,可以使用短路与;2个的话,可以用三元运算符

const flag = true
const loading = falsefunction App(){return (<>{flag && <span>this is span</span>}{loading ? <span>loading...</span>:<span>this is span</span>}</>)
}

JSX高频场景-复杂条件渲染

在这里插入图片描述

需求:列表中需要根据文章的状态适配
解决方案:自定义函数 + 判断语句

const type = 1  // 0|1|3function getArticleJSX(){if(type === 0){return <div>无图模式模版</div>}else if(type === 1){return <div>单图模式模版</div>}else(type === 3){return <div>三图模式模版</div>}
}function App(){return (<>{ getArticleJSX() }</>)
}

我自己写的:

const data = [{ id: 0, title: "文章0", img: [] },{ id: 1, title: "文章1", img: ["../assert/1.png"] },{ id: 2, title: "文章2", img: ["../assert/21.png", "../assert/22.png"] },
];const getImgTemplate = (item) => {if (item.img.length === 0) {return <div></div>;} else if (item.img.length === 1) {return (<div><img src={item.img[0]} alt={item.img[0]} /><img src={item.img[1]} alt={item.img[1]} /></div>);} else if (item.img.length === 2) {return (<div><img src={item.img[0]} alt={item.img[0]} /><img src={item.img[1]} alt={item.img[1]} /><img src={item.img[2]} alt={item.img[2]} /></div>);}
};
function App() {return data.map((item) => <div key={item.id}>{getImgTemplate(item)}</div>);
}export default App;

五、React的事件绑定

基础实现

React中的事件绑定,通过语法 on + 事件名称 = { 事件处理程序 },整体上遵循驼峰命名法

function App(){const clickHandler = ()=>{console.log('button按钮点击了')}return (<button onClick={clickHandler}>click me</button>)
}

使用事件参数

在事件回调函数中设置形参e即可

function App(){const clickHandler = (e)=>{console.log('button按钮点击了', e)}return (<button onClick={clickHandler}>click me</button>)
}

传递自定义参数

语法:事件绑定的位置改造成箭头函数的写法,在执行clickHandler实际处理业务函数的时候传递实参

function App(){const clickHandler = (name)=>{console.log('button按钮点击了', name)}return (<button onClick={()=>clickHandler('jack')}>click me</button>)
}

注意:必须写成箭头函数,如果直接在 JSX 中使用 {clickHandler('jack')},那么这个函数会在每次渲染时被调用,而不是在点击按钮时触发!!!!!!
:::warning
注意:不能直接写函数调用,这里事件绑定需要一个函数引用
:::

同时传递事件对象和自定义参数

语法:在事件绑定的位置传递事件实参e和自定义参数,clickHandler中声明形参,注意顺序对应

注意箭头函数里面也要加参数e

function App(){const clickHandler = (name,e)=>{console.log('button按钮点击了', name,e)}return (<button onClick={(e)=>clickHandler('jack',e)}>click me</button>)
}

六、React组件基础使用

组件是什么

概念:一个组件就是一个用户界面的一部分,它可以有自己的逻辑和外观,组件之间可以互相嵌套,也可以服用多次
在这里插入图片描述

组件基础使用

在React中,一个组件就是首字母大写的函数,内部存放了组件的逻辑和视图UI, 渲染组件只需要把组件当成标签书写即可

// 1. 定义组件
// 写成箭头函数也可以
function Button(){return <button>click me</button>
}// 2. 使用组件
function App(){return (<div>{/* 自闭和 */}<Button/>{/* 成对标签 */}<Button></Button></div>)
}

七、组件状态管理-useState

基础使用

useState 是一个 React Hook(函数),它允许我们向组件添加一个状态变量, 从而控制影响组件的渲染结果
和普通JS变量不同的是,状态变量一旦发生变化组件的视图UI也会跟着变化(数据驱动视图

在这里插入图片描述在这里插入图片描述

// useState实现计数器按钮
import { useState } from "react";
function App() {// 1.调用useState添加一个状态变量const [count, setCount] = useState(0); // 解构// 2. 点击事件回调const handleClick = () => {// 使用setCount的作用:// (1)修改count值// (2)触发组件重新渲染的作用,从而实现了视图的更新setCount(count + 1);};return (<div><button onClick={handleClick}>{count}</button></div>);
}export default App;

状态的修改规则

在React中状态被认为是只读的,我们应该始终替换它而不是修改它, 直接修改状态不能引发视图更新

在这里插入图片描述

修改对象状态

对于对象类型的状态变量,应该始终给set方法一个全新的对象 来进行修改

在这里插入图片描述

// useState实现计数器按钮
import { useState } from "react";
function App() {const [obj, setObj] = useState({ name: "slx", age: 12, sex: "s" });const [newName, setNewName] = useState("");const handleNewName = (e) => {setNewName(e.target.value);};const handleObjName = () => {setObj({ ...obj, name: newName });};return (<div><input type="text" value={newName} onChange={(e) => handleNewName(e)} /><button onClick={handleObjName}>click</button><p>newName:{newName}</p>{/* <p>{obj}</p> */}{/* 不可以这样写,在React中,不能直接将对象  直接渲染到组件中 */}<p>obj.name:{obj.name}</p><p>obj.age:{obj.age}</p><p>obj.sex:{obj.sex}</p></div>);
}export default App;

在这里插入图片描述

八、组件的基础样式处理

React组件基础的样式控制有俩种方式,行内样式和class类名控制

1. 行内样式

注意有短横线的要写成驼峰 font-size fontSize

function App() {return <div style={{ color: "red", backgroundColor: "pink" }}>ddddddd</div>;
}

或者抽出来写

const style = {color: "red",backgroundColor: "pink",
};function App() {return <div style={style}>ddddddd</div>;
}

2. class类名控制

注意是className,并且不用加花括号,直接引号

.foo{color: red;
}
import './index.css'function App(){return (<div><span className="foo">this is span</span></div>)
}

九、【实战项目】B站评论案例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 渲染评论列表
    核心思路:
    - 使用useState维护评论列表
    - 使用map方法对列表进行遍历渲染
    - 注意:图片动态路径写法 <img src={item.user.avatar} />

  2. 删除评论实现

    • 只有自己的评论才显示删除按钮:条件渲染
    {item.user.uid === user.uid && (<span className="delete-btn">删除</span>)}
    
    • 点击删除按钮,删除当前按钮,列表中不在显示:filter过滤id
      const handleDelect = (id) => {// 注意filter返回的是满足条件的元素,所以这里要写成 !==setList(list.filter((item) => item.rpid !== id));
    };
    
         {item.user.uid === user.uid && (<spanclassName="delete-btn"onClick={() => handleDelect(item.rpid)}>删除</span>)}
    
  3. 渲染导航Tab和高亮实现

    • 列表渲染
     {tabs.map((item) => (<span className="nav-item" key={item.type}>{item.text}</span>))}
    
    • 点击谁就把谁的type记录下来
      // 记录typeconst [type, setType] = useState("hot");const handleClick = (type) => {setType(type);console.log(type);};{tabs.map((item) => (<spanclassName="nav-item"key={item.type}onClick={() => handleClick(item.type)}>{item.text}</span>))}
    
    • 通过记录的type和每一项遍历时的type做匹配 控制激活类名的显示
    <span   className={`nav-item ${type===item.type && 'active'}`}key={item.type}onClick={() => handleClick(item.type)}>
    
  4. 评论列表排序功能实现
    需求:点击最新,评论列表倒序排列;点击最热,点赞数最多的在前
    利用开发工具lodash:lodash传送门

    使用前安装:npm i lodash
    引用:import _ from 'lodash' 下划线是使用各种方法的前缀
    使用:

    	 const handleClick = (type) => {setType(type);console.log(type);if (type === "hot") {setList(_.orderBy(list, "like", "desc"));} else if (type === "time") {setList(_.orderBy(list, "ctime", "desc"));}};
    

    已进入页面就自动最热排序:

      const [list, setList] = useState(_.orderBy(defaultList, "hot", "desc"));
    

在这里插入图片描述

基础模版

import { useState } from 'react'
import './App.scss'
import avatar from './images/bozai.png'/*** 评论列表的渲染和操作** 1. 根据状态渲染评论列表* 2. 删除评论*/// 评论列表数据
const defaultList = [{// 评论idrpid: 3,// 用户信息user: {uid: '13258165',avatar: '',uname: '周杰伦',},// 评论内容content: '哎哟,不错哦',// 评论时间ctime: '10-18 08:15',like: 88,},{rpid: 2,user: {uid: '36080105',avatar: '',uname: '许嵩',},content: '我寻你千百度 日出到迟暮',ctime: '11-13 11:29',like: 88,},{rpid: 1,user: {uid: '30009257',avatar,uname: '黑马前端',},content: '学前端就来黑马',ctime: '10-19 09:00',like: 66,},
]
// 当前登录用户信息
const user = {// 用户iduid: '30009257',// 用户头像avatar,// 用户昵称uname: '黑马前端',
}/*** 导航 Tab 的渲染和操作** 1. 渲染导航 Tab 和高亮* 2. 评论列表排序*  最热 => 喜欢数量降序*  最新 => 创建时间降序*/// 导航 Tab 数组
const tabs = [{ type: 'hot', text: '最热' },{ type: 'time', text: '最新' },
]const App = () => {return (<div className="app">{/* 导航 Tab */}<div className="reply-navigation"><ul className="nav-bar"><li className="nav-title"><span className="nav-title-text">评论</span>{/* 评论数量 */}<span className="total-reply">{10}</span></li><li className="nav-sort">{/* 高亮类名: active */}<span className='nav-item'>最新</span><span className='nav-item'>最热</span></li></ul></div><div className="reply-wrap">{/* 发表评论 */}<div className="box-normal">{/* 当前用户头像 */}<div className="reply-box-avatar"><div className="bili-avatar"><img className="bili-avatar-img" src={avatar} alt="用户头像" /></div></div><div className="reply-box-wrap">{/* 评论框 */}<textareaclassName="reply-box-textarea"placeholder="发一条友善的评论"/>{/* 发布按钮 */}<div className="reply-box-send"><div className="send-text">发布</div></div></div></div>{/* 评论列表 */}<div className="reply-list">{/* 评论项 */}<div className="reply-item">{/* 头像 */}<div className="root-reply-avatar"><div className="bili-avatar"><imgclassName="bili-avatar-img"alt=""/></div></div><div className="content-wrap">{/* 用户名 */}<div className="user-info"><div className="user-name">jack</div></div>{/* 评论内容 */}<div className="root-reply"><span className="reply-content">这是一条评论回复</span><div className="reply-info">{/* 评论时间 */}<span className="reply-time">{'2023-11-11'}</span>{/* 评论数量 */}<span className="reply-time">点赞数:{100}</span><span className="delete-btn">删除</span></div></div></div></div></div></div></div>)
}export default App
.app {width: 80%;margin: 50px auto;
}.reply-navigation {margin-bottom: 22px;.nav-bar {display: flex;align-items: center;margin: 0;padding: 0;list-style: none;.nav-title {display: flex;align-items: center;width: 114px;font-size: 20px;.nav-title-text {color: #18191c;font-weight: 500;}.total-reply {margin: 0 36px 0 6px;color: #9499a0;font-weight: normal;font-size: 13px;}}.nav-sort {display: flex;align-items: center;color: #9499a0;font-size: 13px;.nav-item {cursor: pointer;&:hover {color: #00aeec;}&:last-child::after {display: none;}&::after {content: ' ';display: inline-block;height: 10px;width: 1px;margin: -1px 12px;background-color: #9499a0;}}.nav-item.active {color: #18191c;}}}
}.reply-wrap {position: relative;
}
.box-normal {display: flex;transition: 0.2s;.reply-box-avatar {display: flex;align-items: center;justify-content: center;width: 80px;height: 50px;}.reply-box-wrap {display: flex;position: relative;flex: 1;.reply-box-textarea {width: 100%;height: 50px;padding: 5px 10px;box-sizing: border-box;color: #181931;font-family: inherit;line-height: 38px;background-color: #f1f2f3;border: 1px solid #f1f2f3;border-radius: 6px;outline: none;resize: none;transition: 0.2s;&::placeholder {color: #9499a0;font-size: 12px;}&:focus {height: 60px;background-color: #fff;border-color: #c9ccd0;}}}.reply-box-send {position: relative;display: flex;flex-basis: 86px;align-items: center;justify-content: center;margin-left: 10px;border-radius: 4px;cursor: pointer;transition: 0.2s;& .send-text {position: absolute;z-index: 1;color: #fff;font-size: 16px;}&::after {position: absolute;width: 100%;height: 100%;background-color: #00aeec;border-radius: 4px;opacity: 0.5;content: '';}&:hover::after {opacity: 1;}}
}
.bili-avatar {position: relative;display: block;width: 48px;height: 48px;margin: 0;padding: 0;border-radius: 50%;
}
.bili-avatar-img {position: absolute;top: 50%;left: 50%;display: block;width: 48px;height: 48px;object-fit: cover;border: none;border-radius: 50%;image-rendering: -webkit-optimize-contrast;transform: translate(-50%, -50%);
}// 评论列表
.reply-list {margin-top: 14px;
}
.reply-item {padding: 22px 0 0 80px;.root-reply-avatar {position: absolute;left: 0;display: flex;justify-content: center;width: 80px;cursor: pointer;}.content-wrap {position: relative;flex: 1;&::after {content: ' ';display: block;height: 1px;width: 100%;margin-top: 14px;background-color: #e3e5e7;}.user-info {display: flex;align-items: center;margin-bottom: 4px;.user-name {height: 30px;margin-right: 5px;color: #61666d;font-size: 13px;line-height: 30px;cursor: pointer;}}.root-reply {position: relative;padding: 2px 0;color: #181931;font-size: 15px;line-height: 24px;.reply-info {position: relative;display: flex;align-items: center;margin-top: 2px;color: #9499a0;font-size: 13px;.reply-time {width: 76px;margin-right: 20px;}.reply-like {display: flex;align-items: center;margin-right: 19px;.like-icon {width: 14px;height: 14px;margin-right: 5px;color: #9499a0;background-position: -153px -25px;&:hover {background-position: -218px -25px;}}.like-icon.liked {background-position: -154px -89px;}}.reply-dislike {display: flex;align-items: center;margin-right: 19px;.dislike-icon {width: 16px;height: 16px;background-position: -153px -153px;&:hover {background-position: -217px -153px;}}.dislike-icon.disliked {background-position: -154px -217px;}}.delete-btn {cursor: pointer;&:hover {color: #00aeec;}}}}}
}.reply-none {height: 64px;margin-bottom: 80px;color: #99a2aa;font-size: 13px;line-height: 64px;text-align: center;
}

完成版本

 import { useState } from 'react'
import './App.scss'
import avatar from './images/bozai.png'
import orderBy from 'lodash/orderBy'/*** 评论列表的渲染和操作** 1. 根据状态渲染评论列表* 2. 删除评论*/// 评论列表数据
const defaultList = [{// 评论idrpid: 3,// 用户信息user: {uid: '13258165',avatar: '',uname: '周杰伦',},// 评论内容content: '哎哟,不错哦',// 评论时间ctime: '10-18 08:15',like: 88,},{rpid: 2,user: {uid: '36080105',avatar: '',uname: '许嵩',},content: '我寻你千百度 日出到迟暮',ctime: '11-13 11:29',like: 88,},{rpid: 1,user: {uid: '30009257',avatar,uname: '黑马前端',},content: '学前端就来黑马',ctime: '10-19 09:00',like: 66,},
]
// 当前登录用户信息
const user = {// 用户iduid: '30009257',// 用户头像avatar,// 用户昵称uname: '黑马前端',
}/*** 导航 Tab 的渲染和操作** 1. 渲染导航 Tab 和高亮* 2. 评论列表排序*  最热 => 喜欢数量降序*  最新 => 创建时间降序*/// 导航 Tab 数组
const tabs = [{ type: 'hot', text: '最热' },{ type: 'time', text: '最新' },
]const App = () => {// 导航 Tab 高亮的状态const [activeTab, setActiveTab] = useState('hot')const [list, setList] = useState(defaultList)// 删除评论const onDelete = rpid => {// 如果要删除数组中的元素,需要调用 filter 方法,并且一定要调用 setList 才能更新状态setList(list.filter(item => item.rpid !== rpid))}// tab 高亮切换const onToggle = type => {setActiveTab(type)let newListif (type === 'time') {// 按照时间降序排序// orderBy(对谁进行排序, 按照谁来排, 顺序)newList = orderBy(list, 'ctime', 'desc')} else {// 按照喜欢数量降序排序newList = orderBy(list, 'like', 'desc')}setList(newList)}return (<div className="app">{/* 导航 Tab */}<div className="reply-navigation"><ul className="nav-bar"><li className="nav-title"><span className="nav-title-text">评论</span>{/* 评论数量 */}<span className="total-reply">{list.length}</span></li><li className="nav-sort">{/* 高亮类名: active */}{tabs.map(item => {return (<divkey={item.type}className={item.type === activeTab ? 'nav-item active' : 'nav-item'}onClick={() => onToggle(item.type)}>{item.text}</div>)})}</li></ul></div><div className="reply-wrap">{/* 发表评论 */}<div className="box-normal">{/* 当前用户头像 */}<div className="reply-box-avatar"><div className="bili-avatar"><img className="bili-avatar-img" src={avatar} alt="用户头像" /></div></div><div className="reply-box-wrap">{/* 评论框 */}<textareaclassName="reply-box-textarea"placeholder="发一条友善的评论"/>{/* 发布按钮 */}<div className="reply-box-send"><div className="send-text">发布</div></div></div></div>{/* 评论列表 */}<div className="reply-list">{/* 评论项 */}{list.map(item => {return (<div key={item.rpid} className="reply-item">{/* 头像 */}<div className="root-reply-avatar"><div className="bili-avatar"><imgclassName="bili-avatar-img"src={item.user.avatar}alt=""/></div></div><div className="content-wrap">{/* 用户名 */}<div className="user-info"><div className="user-name">{item.user.uname}</div></div>{/* 评论内容 */}<div className="root-reply"><span className="reply-content">{item.content}</span><div className="reply-info">{/* 评论时间 */}<span className="reply-time">{item.ctime}</span>{/* 评论数量 */}<span className="reply-time">点赞数:{item.like}</span>{user.uid === item.user.uid && (<spanclassName="delete-btn"onClick={() => onDelete(item.rpid)}>删除</span>)}</div></div></div></div>)})}</div></div></div>)
}export default App

十、classnames优化类名控制

  • 安装:npm i classnames
  • 导入:import classNames from "classnames";
  • 使用:
     <spanclassName={classNames("nav-item", {active: type === item.type,})}key={item.type}onClick={() => handleClick(item.type)}>{/* className={`nav-item ${type === item.type && "active"}`} */}{item.text}</span>
    

在这里插入图片描述

相关文章:

  • 【大模型】在VS Code(Visual Studio Code)上安装中文汉化版插件
  • [激光原理与应用-78]:激光加工(如打标)的各种笔参数与含义解读
  • MCGS学习——用户管理
  • XUbuntu22.04之安装Plantuml(二百二十三)
  • Camera入门基础知识
  • UGUI源码分析与研究2-从底层实现的角度去分析和调优UI的性能问题和疑难杂症
  • 加载三维模型,加载时黑的?
  • 前端视角如何理解“时间复杂度O(n)”
  • 【算法】小强爱数学(迭代公式+数论取模)
  • Unity学习笔记 6.2D换帧动画
  • Java后端八股----JVM篇
  • RuoYi-Vue-Plus(基础知识点jackson、mybatisplus、redis)
  • 十.pandas方法总结Numpy
  • 数据结构——双向链表(C语言版)
  • 20.Python从入门到精通—参数 位置参数 关键字参数 默认参数 匿名函数 return 语句 强制位置参数
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • Angular 4.x 动态创建组件
  • CSS 三角实现
  • es6
  • extjs4学习之配置
  • js ES6 求数组的交集,并集,还有差集
  • Swift 中的尾递归和蹦床
  • Twitter赢在开放,三年创造奇迹
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 坑!为什么View.startAnimation不起作用?
  • 设计模式 开闭原则
  • 通信类
  • 网页视频流m3u8/ts视频下载
  • 为什么要用IPython/Jupyter?
  • 小程序button引导用户授权
  • 用Visual Studio开发以太坊智能合约
  • 怎么把视频里的音乐提取出来
  • 【云吞铺子】性能抖动剖析(二)
  • Mac 上flink的安装与启动
  • puppet连载22:define用法
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • #预处理和函数的对比以及条件编译
  • (二开)Flink 修改源码拓展 SQL 语法
  • (七)理解angular中的module和injector,即依赖注入
  • (转)清华学霸演讲稿:永远不要说你已经尽力了
  • ***通过什么方式***网吧
  • .java 9 找不到符号_java找不到符号
  • .NET Framework与.NET Framework SDK有什么不同?
  • .NET MVC之AOP
  • .NET NPOI导出Excel详解
  • .Net 垃圾回收机制原理(二)
  • .net开发时的诡异问题,button的onclick事件无效
  • /bin/bash^M: bad interpreter: No such file ordirectory
  • @Autowired自动装配
  • [20150904]exp slow.txt
  • [Angular 基础] - 数据绑定(databinding)
  • [AR]Vumark(下一代条形码)