如何初中学习计划怎么写用Typescript写Reactjs

用TypeScript写前端React遇到的问题,未解决
时间: 16:40:06
&&&& 阅读:308
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&下面是刚开始的webpack的配置文件
var path = require(‘path‘);var webpack = require(‘webpack‘);var OpenBrowserPlugin = require(‘open-browser-webpack-plugin‘);var HtmlWebpackPlugin = require(‘html-webpack-plugin‘);var application ={&&& port:3002,&&& entry:‘./application/index.tsx‘,&&& outputFile: ‘app.js‘,&&& outputDir: ‘dist‘,&&& template: ‘application/index.html‘};module.exports = {&&& entry: application.entry,&&& devtool: "source-map",&&& output: {&&&&&&& filename: application.outputFile,&&&&&&& path: path.resolve(__dirname, application.outputDir),&&& },&&& resolve: {&&&&&&& extensions: [" " , ".ts", ".tsx", ".js", ".json"]&&& },&&& module: {&&&&&&& rules: [&&&&&&&&&&& { test: /\.tsx?$/, loader: "awesome-typescript-loader" },&&&&&&&&&&& { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }&&&&&&& ]&&& },&&& devServer: {&&&&&&& contentBase:path.resolve(__dirname, application.outputDir),&&&&&&& historyApiFallback: true,&&&&&&& port: application.port,&&&&&&& inline: true,&&&&&&& hot: true&&& },&&& plugins: [&&&&&&& new webpack.HotModuleReplacementPlugin(),&&&&&&& new HtmlWebpackPlugin({&&&&&&&&&&& filename: ‘index.html‘,&&&&&&&&&&& template: application.template&&&&&&& }),&&&&&&& new webpack.ProvidePlugin({&&&&&&&&&&& $: "jquery",&&&&&&&&&&& jQuery: "jquery",&&&&&&&&&&& "window.jQuery": "jquery",&&&&&&&&&&& React:‘react‘&&&&&&& }),&&&&&&& new OpenBrowserPlugin({url: ‘http://localhost:‘+ application.port})&&& ]};
写出的入口文件代码是:
import * as React from "react";import * as ReactDOM from "react-dom";
console.dir($)ReactDOM.render(&&& &h2&hhh&/h2&,&&& document.getElementById("app"));
当时老是报错:
Error:(4, 13) TS2304:Cannot find name ‘$‘.
Error:(4, 13) TS2304:Cannot find name ‘jQuery‘.
后来才发现是 npm install --save-dev @types/juqery 的问题
后来想把React在ProvidePlugin当成全局变量,以后就不用再ts文件中import了,
Error:(7, 6) TS2686:‘React‘ refers to a UMD global, but the current file is a module. Consider adding an import instead.
我直接写jsx文件如下:
var React = require("react");
var ReactDOM = require("react-dom");console.dir(jQuery);ReactDOM.render(React.createElement("h2", null, "hhh"), document.getElementById("app"));
var ReactDOM = require("react-dom");console.dir(jQuery);ReactDOM.render(React.createElement("h2", null, "hhh"), document.getElementById("app"));
我大概明白了,
因为是在React中写的&h2&hhh&/h2&是需要编译成React.createElement("h2", null, "hhh") ,所以在TSX文件中需要import React
为什么webpack.ProvidePlugin没有生效呢 , 其实生效了,在编译后的jsx文件中生效了.
那我可以这样写吗
import * as ReactDOM from "react-dom";ReactDOM.render(&&& React.createElement("h2", null, "hhh"),&&& document.getElementById("app"));
发现又报错了.
用TS写React就别想不import React ! 就酱标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!Working with React and TypeScript
An introduction to the development of React applications with Atom and TypeScript
We are about to develop the famous TODO App from the
project using React and TypeScript:
In this post you will learn about the following:
1. Setting up the environment
2. Setting up the project
3. The basics about React components
4. Developing React components with TypeScript
5. Compiling the application
6. Running the application
Let&s get started!
1. Setting up the environment
We will start by setting up the environment:
Download an install Node.js from .
Install TypeScript and tsd using npm:
$ npm install -g typescript tsd
Note: use sudo if you are using OSX
Download and install atom from .
Install the
plugin for atom:
$ apm install atom-typescript
This plugin has some cool features like HTML to TSX:
Or dependency view:
Please visit the
to learn more about the atom-typescript features.
Install the .
This extension helps us to debug React applications by displaying the value of the properties and state of a selected component.
2. Setting up the project
By the end of this tutorial the project structure will be similar to the following one:
├── index.html
├── app.js
├── app.tsx
├── constants.js
├── constants.ts
├── footer.js
├── footer.tsx
├── interfaces.d.ts
├── todoItem.js
├── todoItem.tsx
├── todoModel.js
├── todoModel.ts
├── tsconfig.json
├── utils.js
└── utils.ts
├── node_modules
├── director
├── react
└── todomvc-app-css
├── package.json
├── tsd.json
└── typings
├── react
├── react-global.d.ts
└── react.d.ts
└── tsd.d.ts
Let&s start by creating the application&s root folder.
$ mkdir typescript-react
$ cd typescript-react
Then create new package.json file inside the application&s root folder:
private: true,
dependencies: {
director: &^1.2.0&,
react: &^0.13.3&,
todomvc-app-css: &^2.0.0&
You can then install the project dependencies using npm:
# from the application's root folder
$ npm install
This command should create a folder named node_modules inside the application&s root folder. The node_modules should contain 3 folders named: director, react and
todomvc-app-css.
├── node_modules
├── director
├── react
└── todomvc-app-css
We will now install some TypeScript type definitions files.
Type definitions files are used to declare the interfaces of the public API of third party libraries like React. These interfaces can be used by the IDEs to help us during the development of TypeScript applications with features like IntelliSense.
The type definitions files are also used by the TypeScript compiler to ensure that we are using the third party libraries correctly.
We are going to need the React type definitions. We can install them using the following command:
# from the application's root folder
$ tsd init
$ tsd install react --save
The command above will create a file named tsd.json and a folder named typings in the application&s root folder. The typings
folder should contain a folder named react.
We also need to manually
and save a file named react-global.d.ts under the typings/react folder.
└── typings
├── react
├── react-global.d.ts
└── react.d.ts
└── tsd.d.ts
Now, let&s create the index.html file inside the application&s root folder:
&!doctype html&
&html lang=&en& data-framework=&typescript&&
&meta charset=&utf-8&&
&title&React o TodoMVC&/title&
&link rel=&stylesheet&
href=&node_modules/todomvc-common/base.css&&
&link rel=&stylesheet&
href=&node_modules/todomvc-app-css/index.css&&
&section class=&todoapp&&&/section&
&footer class=&info&&
&p&Double-click to edit a todo&/p&
Created by
&a href=&/remojansen/&&Remo H. Jansen&/a&
&p&Part of &a href=&&&TodoMVC&/a&&/p&
&script type=&text/javascript&
src=&node_modules/react/dist/react-with-addons.js&&
&script type=&text/javascript&
src=&node_modules/director/build/director.js&&
&script type=&text/javascript& src=&js/constants.js&&&/script&
&script type=&text/javascript& src=&js/utils.js&&&/script&
&script type=&text/javascript& src=&js/todoModel.js&&&/script&
&script type=&text/javascript& src=&js/todoItem.js&&&/script&
&script type=&text/javascript& src=&js/footer.js&&&/script&
&script type=&text/javascript& src=&js/app.js&&&/script&
At this point you should have the following files and folders in place:
├── index.html
├── node_modules
├── director
├── react
└── todomvc-app-css
├── package.json
├── tsd.json
└── typings
├── react
├── react-global.d.ts
└── react.d.ts
└── tsd.d.ts
You may have noticed that some of the JavaScript files referenced by our index.html file are missing. We will now proceed to solve that problem.
3. The basics about React components
Components are he main building block of a React application. A component represents a self-contained piece of UI. A component will usually display some data and be able handle some kind of user interaction.
A component can contain child components. The application that we are about to develop is really small, so we will only develop one top-level component named TodoApp.
The TodoApp component will be composed of multiple components, including one TodoFooter component and a list of TodoItem components.
Components differentiate two different sets of data: properties and state.
PropertiesProps (short for properties) are a Component&s configuration, its options if you may. They are received from above and immutable as far as the Component receiving them is concerned.
A Component cannot change its props, but it is responsible for putting together the props of its child Components.
StateThe state starts with a default value when a Component mounts and then suffers from mutations in time (mostly generated from user events). It&s a serialisable representation of one point in time—a snapshot.
A Component manages its own state internally, but—besides setting an initial state—has no business fiddling with the state of its children. You could say the state is private.
When we declare a new React component using TypeScript we must declare the interface of its properties and state as follows:
class SomeComponent ponent&ISomeComponentProps, ISomeComponentState& {
Now that we have our project structure in place and we know the basics about components it is time to start developing our components.
4. Developing React components with TypeScript
Let&s create a new folder named js under the application&s root folder.
We are going to create the following files:
├──interfaces.d.ts
├── constants.ts
├── utils.ts
├── todoModel.js
├── footer.tsx
├── todoItem.tsx
└── app.tsx
Feel free to create them now or do it as we implement each one of them.
interfaces.d.ts
We will use this file to define all the interfaces in our application. We use the extension .d.ts (which is also used by the type definition files) instead of .ts because this file will not be transpiled into a JavaScript file. The file is not transpiled because TypeScript interfaces are not transformed into JavaScript code during the compilation process.
// Defines the interface of the structure of a task
interface ITodo {
id: string,
title: string,
completed: boolean
// Defines the interface of the properties of the TodoItem component
interface ITodoItemProps {
key : string,
editing? :
onSave: (val: any) =&
onDestroy: () =&
onEdit: ()
onCancel: (event : any) =&
onToggle: () =&
// Defines the interface of the state of the TodoItem component
interface ITodoItemState {
editText : string
// Defines the interface of the properties of the Footer component
interface ITodoFooterProps {
completedCount :
onClearCompleted :
nowShowing :
// Defines the TodoModel interface
interface ITodoModel {
todos : Array&ITodo&;
onChanges : Array&any&;
subscribe(onChange);
addTodo(title : string);
toggleAll(checked);
toggle(todoToToggle);
destroy(todo);
save(todoToSave, text);
clearCompleted();
// Defines the interface of the properties of the App component
interface IAppProps {
model : ITodoM
// Defines the interface of the state of the App component
interface IAppState {
editing? :
nowShowing? : string
constants.ts
This file is used to expose some constants. The constants are used to store the numeric value of the keyboard keys (ENTER_KEY and ESCAPE_KEY) that we will use later to set some events listeners.
We will also use some values to identify the currently displayed list of tasks by its status:
COMPLETED_TODOS Used when displaying completed tasks
ACTIVE_TODOS Used when displaying incomplete tasks
ALL_TODOS Used when displaying all tasks
namespace app.constants {
export var ALL_TODOS = 'all';
export var ACTIVE_TODOS = 'active';
export var COMPLETED_TODOS = 'completed';
export var ENTER_KEY = 13;
export var ESCAPE_KEY = 27;
This file contains a class named Utils. The Utils class is no more that a collection of utility static functions.
namespace app.miscelanious {
export class Utils {
// generates a new Universally unique identify (UUID)
// the UUID is used to identify each of the tasks
public static uuid() : string {
/*jshint bitwise:false */
var uuid = '';
for (i = 0; i & 32; i++) {
random = Math.random() * 16 | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += '-';
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
.toString(16);
// adds 's' to the end of a given world when count & 1
public static pluralize(count, word) {
return count === 1 ? word : word + 's';
// stores data using the localStorage API
public static store(namespace, data?) {
if (data) {
return localStorage.setItem(namespace, JSON.stringify(data));
var store = localStorage.getItem(namespace);
return (store && JSON.parse(store)) || [];
// just a helper for inheritance
public static extend(...objs : any[]) : any {
var newObj = {};
for (var i = 0; i & objs. i++) {
var obj = objs[i];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
return newO
todoModel.ts
TodoModel is a generic &model& object. Since this application is really small it may not even be worth separating this logic out, but we do this to demonstrate one way to separate out parts of your application.
/// &reference path=&../typings/react/react-global.d.ts& /&
/// &reference path=&./interfaces.d.ts&/&
namespace app.models {
export class TodoModel implements ITodoModel {
public key :
// key used for local storage
public todos : Array&ITodo&;
// a list of tasks
public onChanges : Array&any&;
// a list of events
constructor(key) {
this.key =
this.todos = app.miscelanious.Utils.store(key);
this.onChanges = [];
// the following are some methods
// used to manipulate the list of tasks
public subscribe(onChange) {
this.onChanges.push(onChange);
public inform() {
app.miscelanious.Utils.store(this.key, this.todos);
this.onChanges.forEach(function (cb) { cb(); });
public addTodo(title : string) {
this.todos = this.todos.concat({
id: app.miscelanious.Utils.uuid(),
title: title,
completed: false
public toggleAll(checked) {
// Note: it's usually better to use immutable
// data structures since they're easier to
// reason about and React works very
// well with them. That's why we use
// map() and filter() everywhere instead of
// mutating the array or todo items themselves.
this.todos = this.todos.map&ITodo&((todo : ITodo) =& {
return app.miscelanious.Utils.extend(
{}, todo, {completed: checked}
public toggle(todoToToggle) {
this.todos = this.todos.map&ITodo&((todo : ITodo) =& {
return todo !== todoToToggle ?
app.miscelanious.Utils.extend(
{}, todo, {completed: !pleted}
public destroy(todo) {
this.todos = this.todos.filter(function (candidate) {
return candidate !==
public save(todoToSave, text) {
this.todos = this.todos.map(function (todo) {
return todo !== todoToSave ? todo : app.miscelanious.Utils.extend({}, todo, {title: text});
public clearCompleted() {
this.todos = this.todos.filter(function (todo) {
This file uses the .tsx extension instead of the .ts extension because it contains some TSX code.
TSX is a typed superset of JSX. We will use TSX instead of HTML of client-side templates like Handlebars because TSX and JSX are
used to generate an in-memory representation of the DOM. When the components state or properties change Reacts calculates the most efficient way to update the in-memory representation of the DOM and then proceeds to apply those changes to the real DOM. This process makes React highly efficient when it comes to DOM manipulation.
Note: We need use some extra compiler options to compile .tsx. We will learn more about this topic towards the end of this post.
The footer component allows users to filter the lists of tasks by their status and displays the count of tasks. This component has no state (Note how {} is passed to ponent as the interface of its state) but it has some properties (ITodoFooterProps) that are set by its parent component (the TodoApp component).
/// &reference path=&../typings/react/react-global.d.ts& /&
/// &reference path=&./interfaces.d.ts&/&
export class TodoFooter ponent&ITodoFooterProps, {}& {
public render() {
var activeTodoWord = app.miscelanious.Utils.pluralize(this.props.count, 'item');
var clearButton =
if (pletedCount & 0) {
clearButton = (
className=&clear-completed&
onClick={this.props.onClearCompleted}&
Clear completed
// React idiom for shortcutting to `classSet` since it'll be used often
var cx = React.addons.classS
var nowShowing = this.props.nowS
&footer className=&footer&&
&span className=&todo-count&&
&strong&{this.props.count}&/strong& {activeTodoWord} left
&ul className=&filters&&
className={cx({selected: nowShowing === app.constants.ALL_TODOS})}&
{' '}
href=&#/active&
className={cx({selected: nowShowing === app.constants.ACTIVE_TODOS})}&
{' '}
href=&#/completed&
className={cx({selected: nowShowing === PLETED_TODOS})}&
{clearButton}
todoItem.tsx
The TodoItem component represents one of the tasks in the list of tasks.
This component has both properties (ITodoItemProps) and state (ITodoItemState).
The component initial&s state is set in the component&s constructor by itself while the properties are passed as constructor arguments and are set by the component&s parent component (the TodoApp component).
/// &reference path=&../typings/react/react-global.d.ts& /&
/// &reference path=&./interfaces.d.ts&/&
export class TodoItem ponent&ITodoItemProps, ITodoItemState& {
constructor(props : ITodoItemProps){
super(props);
// set initial state
this.state = { editText: this.props.todo.title };
public handleSubmit(event) {
var val = this.state.editText.trim();
if (val) {
this.props.onSave(val);
this.setState({editText: val});
this.props.onDestroy();
public handleEdit() {
this.props.onEdit();
this.setState({editText: this.props.todo.title});
public handleKeyDown(event) {
if (event.which === app.constants.ESCAPE_KEY) {
this.setState({editText: this.props.todo.title});
this.props.onCancel(event);
} else if (event.which === app.constants.ENTER_KEY) {
this.handleSubmit(event);
public handleChange(event) {
this.setState({editText: event.target.value});
// This is a completely optional performance enhancement
// that you can implement on any React component. If you
// were to delete this method the app would still work
// correctly (and still be very performant!), we just use it
// as an example of how little code it takes to get an order
// of magnitude performance improvement.
public shouldComponentUpdate(nextProps, nextState) {
nextProps.todo !== this.props.todo ||
nextProps.editing !== this.props.editing ||
nextState.editText !== this.state.editText
// Safely manipulate the DOM after updating the state
// when invoking this.props.onEdit() in the handleEdit
// method above.
public componentDidUpdate(prevProps) {
if (!prevProps.editing && this.props.editing) {
var node = React.findDOMNode&HTMLInputElement&(this.refs[&editField&]);
node.focus();
node.setSelectionRange(node.value.length, node.value.length);
public render() {
&li className={React.addons.classSet({
completed: this.pleted,
editing: this.props.editing
&div className=&view&&
className=&toggle&
type=&checkbox&
checked={this.pleted}
onChange={this.props.onToggle}
&label onDoubleClick={ e =& this.handleEdit() }&
{this.props.todo.title}
&button className=&destroy& onClick={this.props.onDestroy} /&
ref=&editField&
className=&edit&
value={this.state.editText}
onBlur={ e =& this.handleSubmit(e) }
onChange={ e =& this.handleChange(e) }
onKeyDown={ e =& this.handleKeyDown(e) }
This file contains the application&s entry point and the declaration of the TodoApp component which is the only top-level component in this application.
/// &reference path=&../typings/react/react-global.d.ts& /&
/// &reference path=&./interfaces.d.ts&/&
// We should have installed a type declaration file but
// for the director npm package but it is not available
// so we will use this declaration to avoid compilation
// errors for now.
declare var Router :
var TodoModel = app.models.TodoM
var TodoFooter = ponents.TodoF
var TodoItem = ponents.TodoI
export class TodoApp ponent&IAppProps, IAppState& {
constructor(props : IAppProps) {
super(props);
this.state = {
nowShowing: app.constants.ALL_TODOS,
editing: null
public componentDidMount() {
var setState = this.setS
// we will configure the Router here
// our router is provided by the
// director npm module
// the router observes changes in the URL and
// triggers some component's event accordingly
var router = Router({
'/': setState.bind(this, {nowShowing: app.constants.ALL_TODOS}),
'/active': setState.bind(this, {nowShowing: app.constants.ACTIVE_TODOS}),
'/completed': setState.bind(this, {nowShowing: PLETED_TODOS})
router.init('/');
public handleNewTodoKeyDown(event) {
if (event.keyCode !== app.constants.ENTER_KEY) {
event.preventDefault();
var val = React.findDOMNode&HTMLInputElement&(this.refs[&newField&]).value.trim();
if (val) {
this.props.model.addTodo(val);
React.findDOMNode&HTMLInputElement&(this.refs[&newField&]).value = '';
public toggleAll(event) {
var checked = event.target.
this.props.model.toggleAll(checked);
public toggle(todoToToggle) {
this.props.model.toggle(todoToToggle);
public destroy(todo) {
this.props.model.destroy(todo);
public edit(todo) {
this.setState({editing: todo.id});
public save(todoToSave, text) {
this.props.model.save(todoToSave, text);
this.setState({editing: null});
public cancel() {
this.setState({editing: null});
public clearCompleted() {
this.props.model.clearCompleted();
// the JSX syntax is quite intuitive but check out
// https://facebook.github.io/react/docs/jsx-in-depth.html
// if you need additional help
public render() {
var todos = this.props.model.
var shownTodos = todos.filter(function (todo) {
switch (this.state.nowShowing) {
case app.constants.ACTIVE_TODOS:
case PLETED_TODOS:
var todoItems = shownTodos.map(function (todo) {
key={todo.id}
todo={todo}
onToggle={this.toggle.bind(this, todo)}
onDestroy={this.destroy.bind(this, todo)}
onEdit={this.edit.bind(this, todo)}
editing={this.state.editing === todo.id}
onSave={this.save.bind(this, todo)}
onCancel={ e =& this.cancel() }
var activeTodoCount = todos.reduce(function (accum, todo) {
pleted ? accum : accum + 1;
var completedCount = todos.length - activeTodoC
if (activeTodoCount || completedCount) {
&TodoFooter
count={activeTodoCount}
completedCount={completedCount}
nowShowing={this.state.nowShowing}
onClearCompleted={ e=& this.clearCompleted() }
if (todos.length) {
&section className=&main&&
className=&toggle-all&
type=&checkbox&
onChange={ e =& this.toggleAll(e) }
checked={activeTodoCount === 0}
&ul className=&todo-list&&
{todoItems}
&/section&
&header className=&header&&
&h1&todos&/h1&
ref=&newField&
className=&new-todo&
placeholder=&What needs to be done?&
onKeyDown={ e =& this.handleNewTodoKeyDown(e) }
autoFocus={true}
var model = new TodoModel('react-todos');
var TodoApp = ponents.TodoA
function render() {
React.render(
&TodoApp model={model}/&,
document.getElementsByClassName('todoapp')[0]
model.subscribe(render);
Make sure that the this operator is pointing to the right element at all times. For example, you should use arrow functions:
onKeyDown={ e =& this.handleNewTodoKeyDown(e) }
instead of
onKeyDown={ this.handleNewTodoKeyDown }
To ensure that the this operator is pointing to the component inside the handleNewTodoKeyDown function.
5. Compiling the application
To compile our application we must add a file named tsconfig.json under the js folder:
&compilerOptions&: {
&target&: &es5&,
&module&: &commonjs&,
&moduleResolution&: &node&,
&isolatedModules&: false,
&jsx&: &react&,
&experimentalDecorators&: true,
&emitDecoratorMetadata&: true,
&declaration&: false,
&noImplicitAny&: false,
&removeComments&: true,
&noLib&: false,
&preserveConstEnums&: true,
&suppressImplicitAnyIndexErrors&: true
&filesGlob&: [
&**/*.ts&,
&**/*.tsx&,
&!node_modules/**&
&files&: [
&constants.ts&,
&interfaces.d.ts&,
&todoModel.ts&,
&utils.ts&,
&app.tsx&,
&footer.tsx&,
&todoItem.tsx&
&exclude&: []
If we check out the
we can find out how to use the tsconfig.json file:
The --project or -p can be used to compile the project in the given directory. The directory needs to contain a tsconfig.json file to direct compilation.
We can compile our application using the following command:
# from the application's root folder
$ tsc -p js
This should create the following JavaScript files under the js folder:
├── app.js
├── constants.js
├── footer.js
├── todoItem.js
├── todoModel.js
└── utils.ts
These are the files that were referenced in our index.html file:
&script type=&text/javascript& src=&js/constants.js&&&/script&
&script type=&text/javascript& src=&js/utils.js&&&/script&
&script type=&text/javascript& src=&js/todoModel.js&&&/script&
&script type=&text/javascript& src=&js/todoItem.js&&&/script&
&script type=&text/javascript& src=&js/footer.js&&&/script&
&script type=&text/javascript& src=&js/app.js&&&/script&
We are now ready to run our application.
6. Running the application
To run the application, we need a web server. We will use the npm module
We can install this package using the following commmand:
$ npm install -g http-server
Note: use sudo if you are using OSX
Use the following command to run the application:
# from the application's root folder
$ http-server
If you open a browser and navigate to http://127.0.0.1:8080/ you should be able to see the application running:
Remember to open the chrome developer tools to take a look to the React developer tools extension for chrome and how the value of the properties and state of the components change as you interact with the application.
7. Conclusions
In this post we have learned how to set up a development environment and create a new project to work with TypeScript and React.
You can browse the source code online at .
Are you thirsty for more? If so, check out
We will keep this blog updated and write more about React and TypeScript in the future.
if you don&t want to miss it out!
Please feel free to talk about this article with us via}

我要回帖

更多关于 二年级写话大全100字 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信