MERN client行ってみよう
MERN client準備編
目次
- コンポーネントの雛形作成
- スタイル適応の準備
- reducer作成
前回の続きです。
今回はクライアントの処理を書いていきます。
今回作成していくもの
コンポーネントの雛形作成
ターミナルでclientに移動してパッケージをインストールします
% cd client % npm install @material-ui/core
次にclientフォルダー直下にcomponentsフォルダーを作成して
さらにその下にフォルダーを作っていきます。
Formフォルダーを作成し、その中にForm.jsファイルを作成
Postsフォルダーを作成し、その中に Posts.jsファイルを作成
PostsフォルダーにPostフォルダーを作成し、その中にPost.jsファイルを作成します。
次にAppコンポーネントを書いていきます。
client/src/App.js
import React from 'react'; // @material-ui/coreからコンポーネントをimport import { Container, AppBar, Typography, Grow, Grid } from '@material-ui/core' // 画像をimport import memories from './images/memories.jpg' const App = () => { return ( <Container maxWidth='lg'> {/* title部分 */} <AppBar position='static' color='inherit'> <Typography variant='h2' align='center' height='60'>memories</Typography> <img src={memories} alt='memories' height='60'/>{/* importした画像 */} </AppBar> {/* main部分 */} <Grow in> <Container> <Grid container justifyContent='space-between' alignItems='stretch' spacing={3}> {/* 投稿一覧が表示される部分 */} <Grid item xs={12} sm={7}> {/* 投稿一覧表示コンポーネント */} <Posts /> </Grid> {/* 投稿フォームが表示される部分 */} <Grid item xs={12} sm={4}> {/* 投稿フォーム表示コンポーネント */} <Form /> </Grid> </Grid> </Container> </Grow> </Container> ); }; export default App;
Formコンポーネントを追記
client/src/components/Form/Form.js
import React from 'react'; const Form = () => { return ( <h1> FORM </h1> ); }; export default Form;
Postsコンポーネントを追記
client/src/components/Posts/Posts.js
import React from 'react'; import Post from './Post/Post' const Posts = () => { return ( <> <h1>POSTS</h1> <Post/> <Post/> </> ); }; export default Posts;
Postコンポーネントを追記
client/src/components/Posts/Post/Post.js
import React from 'react'; const Post = () => { return ( <h1>POST</h1> ); }; export default Post;
client/src/App.jsのimport部分に下記のように追記します。
import React from 'react'; import Posts from './components/Posts/Posts'; //追記 import Form from './components/Form/Form'; //追記 // @material-ui/coreからコンポーネントをimport import { Container, AppBar, Typography, Grow, Grid } from '@material-ui/core' // 画像をimport import memories from './images/memories.jpg'
現状このように画面が表示されています。
スタイルは当ててないので画像は変な感じになってると思います。
スタイル適応の準備
スタイルを当てていきます。
まずは各フォルダーにstyles.jsというファイルを作っていきます。
client/src/styles.js
client/src/components/Form/styles.js
client/src/components/Posts/styles.js
client/src/components/Posts/Post/styles.js
次に各ファイルの中身を書いていきます。
client/src/styles.js
import { makeStyles } from "@material-ui/core/styles"; export default makeStyles((theme) => ({ appBar: { borderRadius: 15, margin: '30px 0', display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, heading: { color: 'rgba(0,183,255, 1)', }, image: { marginLeft: '15px', }, [theme.breakpoints.down('sm')]: { mainContainer: { flexDirection: 'column-reverse' } }, }))
client/src/Form/styles.js
import { makeStyles } from '@material-ui/core/styles'; export default makeStyles((theme) => ({ root: { '& .MuiTextField-root': { margin: theme.spacing(1), }, }, paper: { padding: theme.spacing(2), }, form: { display: 'flex', flexWrap: 'wrap', justifyContent: 'center', }, fileInput: { width: '97%', margin: '10px 0', }, buttonSubmit: { marginBottom: 10, }, }));
client/src/Posts/styles.js
import { makeStyles } from '@material-ui/core/styles'; export default makeStyles((theme) => ({ mainContainer: { display: 'flex', alignItems: 'center', }, smMargin: { margin: theme.spacing(1), }, actionDiv: { textAlign: 'center', }, }));
client/src/Posts/Post/styles.js
import { makeStyles } from '@material-ui/core/styles'; export default makeStyles({ media: { height: 0, paddingTop: '56.25%', backgroundColor: 'rgba(0, 0, 0, 0.5)', backgroundBlendMode: 'darken', }, border: { border: 'solid', }, fullHeightCard: { height: '100%', }, card: { display: 'flex', flexDirection: 'column', justifyContent: 'space-between', borderRadius: '15px', height: '100%', position: 'relative', }, overlay: { position: 'absolute', top: '20px', left: '20px', color: 'white', }, overlay2: { position: 'absolute', top: '20px', right: '20px', color: 'white', }, grid: { display: 'flex', }, details: { display: 'flex', justifyContent: 'space-between', margin: '20px', }, title: { padding: '0 16px', }, cardActions: { padding: '0 16px 8px 16px', display: 'flex', justifyContent: 'space-between', }, });
それぞれのコンポーネントで呼び出して定義をしておきます。
client/src/App.js
import React, { useEffect } from 'react'; import Posts from './components/Posts/Posts'; //追記 import Form from './components/Form/Form'; //追記 // @material-ui/coreからコンポーネントをimport import { Container, AppBar, Typography, Grow, Grid } from '@material-ui/core' // 画像をimport import memories from './images/memories.jpg' import useStyles from './styles' //追記 const App = () => { const classes = useStyles() //追記 return ( <Container maxWidth='lg'> {/* title部分 */} <AppBar className={classes.appBar} position='static' color='inherit'> <Typography className={classes.heading} variant='h2' align='center' height='60'>memories</Typography> <img className={classes.image} src={memories} alt='memories' height='60'/>{/* importした画像 */} </AppBar> {/* main部分 */} <Grow in> <Container> <Grid container justifyContent='space-between' alignItems='stretch' spacing={3}> {/* 投稿一覧が表示される部分 */} <Grid item xs={12} sm={7}> {/* 投稿一覧表示コンポーネント */} <Posts /> </Grid> {/* 投稿フォームが表示される部分 */} <Grid item xs={12} sm={4}> {/* 投稿フォーム表示コンポーネント */} <Form /> </Grid> </Grid> </Container> </Grow> </Container> ); }; export default App;
client/src/components/Form/Form.js
import React from 'react'; import useStyles from './styles' //追記 const Form = () => { const classes = useStyles() //追記 return ( <h1> FORM </h1> ); }; export default Form;
client/src/components/Posts/Posts.js
import React from 'react'; import Post from './Post/Post' import useStyles from './styles' //追記 const Posts = () => { const classes = useStyles() //追記 return ( <> <h1>POSTS</h1> <Post/> <Post/> </> ); }; export default Posts;
client/src/components/Posts/Post/Post.js
import React from 'react'; import useStyles from './styles' const Post = () => { const classes = useStyles() return ( <h1>POST</h1> ); }; export default Post;
reducer作成
次にapiをまとめるフォルダーを作ります
client/src直下にapiというフォルダーを作成してindex.jsファイルを作成します。
同じくclient/src直下にaction, reducersというフォルダーを用意し、それぞれにposts.jsというファイルを用意します。reducersにはindex.jsファイルも用意します。
それではそれぞれの中身を書いていきます。
の前にreact-reduxをインストールします
% cd client % npm install react-redux
中身を書いていきます。
client/src/reducers/index.js
import { combineReducers } from "redux"; // client/src/reducers/postsをimport import posts from './posts' // combineReducersにpostsを登録する export default combineReducers({ posts, })
client/src/reducers/posts.js
// 即時関数をそのままexport default export default (posts = [], action) => { // state(今回の場合はposts)とactionを引数に取る switch (action.type) { case 'FETCH_ALL': return action.payload case 'CREATE': return posts default: return posts; } }
client/src/actions/posts.js
// client/apiの全てをimport import * as api from '../api' // Action Creators 実処理 export const getPosts = () => async (dispatch) => { // 非同期 try { // client/api/index.jsのfetchPosts関数を実行 const { data } = await api.fetchPosts() // actionにtypeとpayloadを渡す payloadには上で取得したdataを格納する dispatch({type: 'FETCH_ALL', payload: data}) } catch (error) { console.log(error.message) } }
client/src/index.js
import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' //追記 import { createStore, applyMiddleware, compose } from 'redux' //追記 import thunk from 'redux-thunk' //追記 import reducers from './reducers' //追記 import App from './App' // client/reducers/からreducerをimportし、storeを作成する const store = createStore(reducers, compose(applyMiddleware(thunk))) ReactDOM.render( // ストアを使用する範囲をProviderで囲みstoreに上で作成したstoreを定義 <Provider store={store}> <App /> </Provider>, document.getElementById('root') )
client/src/App.jsも追記します
import React, { useEffect } from 'react'; import Posts from './components/Posts/Posts'; //追記 import Form from './components/Form/Form'; //追記 // @material-ui/coreからコンポーネントをimport import { Container, AppBar, Typography, Grow, Grid } from '@material-ui/core' // dispatch使用に使うhooks import { useDispatch } from 'react-redux' // client/src/actionsからgetPosts関数をimport import { getPosts } from './actions/posts' // 画像をimport import memories from './images/memories.jpg' import useStyles from './styles' const App = () => { const classes = useStyles() // dispatchを定義 const dispatch = useDispatch() useEffect(() => { // getPosts関数を実行 dispatch(getPosts()) },[dispatch]) return ( <Container maxWidth='lg'> {/* title部分 */} <AppBar className={classes.appBar} position='static' color='inherit'> <Typography className={classes.heading} variant='h2' align='center' height='60'>memories</Typography> <img className={classes.image} src={memories} alt='memories' height='60'/>{/* importした画像 */} </AppBar> {/* main部分 */} <Grow in> <Container> <Grid container justifyContent='space-between' alignItems='stretch' spacing={3}> {/* 投稿一覧が表示される部分 */} <Grid item xs={12} sm={7}> {/* 投稿一覧表示コンポーネント */} <Posts /> </Grid> {/* 投稿フォームが表示される部分 */} <Grid item xs={12} sm={4}> {/* 投稿フォーム表示コンポーネント */} <Form /> </Grid> </Grid> </Container> </Grow> </Container> ); }; export default App;
ややこしくなってきたので一旦図でまとめてみました。
間違ってたら教えてください・・・
長くなってきたので今回はここまでにします。
現在のclientのフォルダ構成はこんな感じになってると思います。
次回も引き続きクライアント側の表示/投稿処理を実装していきます。
今回はここまで
続きは次回!
それではまた!
MERN serverセットアップ
MERN Server処理準備編
目次
- routeの作成
- controllerの作成
- modelの作成
- server/一覧表示・投稿処理の作成
前回の続きです。
今回はサーバーの処理を書いていきます。
今回作成していくもの
routeの作成
まずはserverディレクトリにroutesというディレクトリを作成します。
その中にposts.jsを作成します。
server/routes/posts.js import express from "express" //expressのルーターを定義 const router = express.Router(); // localhost:5001/posts でここに入ってくる。 router.get('/', (req, res) => { res.send('THIS WORKS!') }) export default router
次にserver/index.jsに追記し、上で書いたposts.jsをimportします。
server/index.js import express from 'express' import bodyParser from 'body-parser' import mongoose from 'mongoose' import cors from 'cors' import postRoutes from './routes/posts.js' //追記 const app = express() // 追記 app.use('/posts', postRoutes) // /postsで始まるURLは全てpostRoutes(/routes/posts.js)で処理される。 app.use(bodyParser.json({limit: '30mb', extended: true})) app.use(bodyParser.urlencoded({limit: '30mb', extended: true})) app.use(cors()) const CONNECTION_URL = "mongodb+srv://ユーザー:パスワード@cluster0.mjyb6.mongodb.net/myFirstDatabase?retryWrites=true&w=majority" const PORT = process.env.PORT || 5001 mongoose.connect(CONNECTION_URL, { useNewUrlParser: true, useUnifiedTopology: true}) .then(() => app.listen(PORT, () => console.log(`Server running on port ${PORT}`))) .catch((error) => console.log(error.message))
これでlocalhost:5001/postsにアクセスすると下のような画面が表示されるかと思います。
次に機能を実装する前にフォルダ構成を整えていきます。
controllerの作成
まずserver直下にcontrollersディレクトリを作成し、その中にposts.jsを作成します。
server/controllers/posts.js export const getPosts = (req, res) => { res.send('THIS WORKS!') }
次にserver/routes/posts.jsを修正します。
server/routes/posts.js import express from "express" import { getPosts } from "../controllers/posts.js"; //controllers/posts.jsのgetPost関数をimport //expressのルーターを定義 const router = express.Router(); // localhost:5001/posts でここに入ってくる。 router.get('/', getPosts) //localhost:5001/postsで controllers/posts.jsのgetPostsが実行される。 export default router
modelの作成
server直下にmodelsディレクトリを作成し、postMessage.jsを作成します。
server/models/postMessage.js import mongoose from 'mongoose' // 投稿内容のデータの形を定義 const postSchema = mongoose.Schema({ // 投稿のタイトル title: String, // 投稿の本文 message: String, // 投稿者 creator: String, // タグ tags: [String], // 画像ファイル selectedFile: String, // イイねの数 likeCount: { type: Number, default: 0 }, // 作成日時 createdAt: { type: Date, default: new Date() }, }) // PostMessageという名前のコレクションでpostSchemaで定義したデータ構造であることを定義 const PostMessage = mongoose.model('PostMessage', postSchema) export default PostMessage
server/一覧表示・投稿処理の作成
処理を実装していきます。
まずはserver/controllers/posts.jsを変更していきます。
server/controllers/posts.js // PostMessageモデルをimport import PostMessage from "../models/postMessage.js" export const getPosts = async (req, res) => { // 非同期処理にするのでasyncをつけます // 成功処理 try { // DBからpostMessageを全て取得 const postMessages = await PostMessage.find() // 取得したデータをコンソールに出力 console.log(postMessages) // レスポンスのステータスを200にしjson化したpostMessagesを返却 res.status(200).json(postMessages) } catch (error) { // 失敗処理 // レスポンスを404に設定しエラーを返す res.status(404).json({message: error.message}) } }
localhost:5001/postsにアクセスすると空の配列が返ってきます。これはまだ投稿データがないためです。
次に投稿処理を簡単に実装します。
server/controllers/posts.js export const createPost = async (req, res) => { // クライアントからのデータを定義 const post = req.body // modelで定義したPostMessageのインスタンスを作成 const newPost = new PostMessage(post) try { // DBにデータを保存 await newPost.save() res.status(201).json(newPost) } catch (error) { res.status(409).json({ message: error.message }) }
server/routes/posts.jsにもこの関数をimportしてルーティングを定義しておきます。
server/routes/posts.js import express from "express" import { getPosts, createPost } from "../controllers/posts.js"; //createPostを追記 //expressのルーターを定義 const router = express.Router(); // localhost:5001/posts でここに入ってくる。 router.get('/', getPosts) //localhost:5001/postsで controllers/posts.jsのgetPostsが実行される。 router.post('/', createPost) //追記 export default router
httpステータスコードについて詳しく知りたい方は下記にアクセスしてみてください。
ざっくりだと
-
200番台
成功
-
300番台
リダイレクト
-
400番台
クライアントエラー
-
500番台
サーバーエラー
という感じになっているようです。
これでserver側の基本的な一覧表示と投稿処理ができました。
次回はクライアント側の投稿処理を実装していきます。
今回はここまで
続きは次回!
それではまた!
MERN環境構築
MERN環境構築編
目次
- 参考動画
- 環境構築
今回からMERNスタックについて書いていきます。
MERNとは
- MongoDB
- Express
- React
- Node
の略です。これらを使用して簡単なアプリケーションを作っていきます。
今回学習に使用させていただいた動画がこちら
MERNについては英語の記事多め、動画もUdemyも英語ばっかり
自分自身もUdemyに日本語対応している講座がなくて、この動画を見て勉強させてもらいました。
この動画を見ながらGoogle先生が翻訳して字幕を出してくれるのですが・・・
んーわからない!
それでもなんとかアプリ自体は作れましたので
自分の備忘録として何回かに渡って進め方を書いていこうと思います。
英語にアレルギーがある方はぜひ参考にしていただければと思います。
まあ余裕っしょって方は上記の動画を参考に
今回作成していくもの
環境構築
まずは任意の場所にフォルダーを作成します。
今回はデスクトップに「memories101」というフォルダーを作成し、vscodeでそのフォルダーを開きます。
クライアント用とサーバー用にターミナルを二つ開きます。
memories101直下にclientディレクトリ、serverディレクトリを作成します。
先ほど開いたターミナルでそれぞれのディレクトリに移動します。
% cd client
% cd server
client側でReactをインストールします。
前提としてNode.jsのLTSをインストールしといてください。
% npx create-react-app ./
serverディレクトリ直下にindex.jsファイルを作成します。
serverディレクトリにpackege.jsonを作成します。
% npm init -y
そのままserverディレクトリで必要なパッケージをインストールしていきます。
% npm install body-parser cors express mongoose nodemon
インストールが終了したらserver側のpackage.jsonを以下に書き換えます。
server/package.json
{ "name": "server", "version": "1.0.0", "description": "", "main": "index.js", "type": "module", "scripts": { "start": "nodemon index.js" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "body-parser": "^1.19.1", "cors": "^2.8.5", "express": "^4.17.2", "mongoose": "^6.2.0", "nodemon": "^2.0.15" } }
server/index.jsに以下を追記しimportします。
server/index.js
import express from 'express' import bodyParser from 'body-parser' import mongoose from 'mongoose' import cors from 'cors'
client側のターミナルに戻り必要なパッケージをインストールしていきます。
% npm install axios moment react-file-base64 redux redux-thunk
create-react-appで作成されたsrcディレクトリにはいろいろなものが含まれていますが、使用しないものが多々あるので一旦これを削除し、新しくsrcディレクトリを作成します。
新たに作成したsrc直下にindex.jsファイルを作成します。
client/src/index.js
import React from 'react' import ReactDOM from 'react-dom' import App from './App' ReactDOM.render(<App />, document.getElementById('root'))
同階層にApp.jsを作成します。
client/src/App.js
import React from 'react'; const App = () => { return ( <div>App</div> ); }; export default App;
clientディレクトリのターミナル
% npm start
こんな画面が表示されます。
続いてサーバー側のセットアップをしていきます。
今回DBはmongoDB Atlasを使用していきます。
まずはDBを作成していきます。
mongodb.comにアクセスし、Try Freeをクリック
使用目的っぽいアンケートをテキトーに埋める
プライバシーポリシーと規約に同意してsubmit
sharedというのが無料なので、これを選択し、Create Cluster
3~5分くらいかかるよーと言われるので
その間にDB使用ユーザーを作成する
左のメニューバーのDatabase Accessをクリック
Add New Database Userをクリック
赤枠上段に任意のユーザー名、下段にパスワードを入力する。
Add Userをクリック
次にネットワークを追加します。
左のメニューバーのNetwork Access→Add IP Address
Add Current IP Address
Access List Entryという部分に自動でIPが入力されるので、confirm
ここがpendingになって
Active
左のメニューバーのDatabases→Connect→Connect Your Application
Copy
server/index.jsを編集
server/index.js
import express from 'express' import bodyParser from 'body-parser' import mongoose from 'mongoose' import cors from 'cors' const app = express() app.use(bodyParser.json({limit: '30mb', extended: true})) app.use(bodyParser.urlencoded({limit: '30mb', extended: true})) app.use(cors()) //先ほどコピーしてきたものをここにペースト const CONNECTION_URL = "mongodb+srv://ユーザー:パスワード@cluster0.mjyb6.mongodb.net/myFirstDatabase?retryWrites=true&w=majority" const PORT = process.env.PORT || 5001 mongoose.connect(CONNECTION_URL, { useNewUrlParser: true, useUnifiedTopology: true}) .then(() => app.listen(PORT, () => console.log(`Server running on port ${PORT}`))) .catch((error) => console.log(error.message))
ターミナルのserverディレクトリで
% npm start
Server running on port 5001と表示されれば正常にDBと接続できています。
これで基本的な環境構築はできました。
次回からは本格的にコードを書き始めます。
今回はここまで
続きは次回!
それではまた!
children().children()とかやってないよね?
jQuery備忘録 Vol.2
目次
- children().children()とかやってないよね?
今回は子要素以下の特定の要素を取得する方法です。
find()
index.html
<body> <div> <p>children().children()とかやってないよね?!</p> <div class='content'> <ul class="ul_1"> <li id='1'>1</li> <li id='2'>2</li> <li id='3'>3</li> </ul> <button class="button">はいっ!</button> </div> <div class='content'> <ul class="ul_2"> <li id='4'>4</li> <li id='5'>5</li> <li id='6'>6</li> </ul> <button class="button">はいっ!</button> </div> <div class='content'> <ul class="ul_3"> <li id='7'>7</li> <li id='8'>8</li> <li id='9'>9</li> </ul> <button id="surprise" class="button">はいっ!</button> </div> </div> <script> $(function(){ $('button').on('click', function(){ if( $(this).attr('id') == 'surprise' ){ supEl = $(this).parent().find('ul') $(supEl).empty() $('<img>', {src: '3596948_s.jpg',}).appendTo(supEl) }else{ els = $(this).parent().find('li') $.each(els, function(index, val){ $(val).text('あぁぁぁぁぁ') }) } }) }) </script> </body>
find()で要素を探すことができます。
find('div') find('.class') find('#id')
こんな探し方もできるのでやってみてください!
今回はここまで
それではまた次回!
jQueryでHTML要素を作成
jQuery備忘録 Vol.1
目次
- jQueryでHTML要素を作成
ご無沙汰になってしまいました。今回は業務中に使用したjQueryの備忘録となっています。
全く更新していなかったのですが、ちょこちょこアクセスがあるようで・・・ありがとうございます。
頑張って更新していきますので、お役に立てればと思います。
jQueryでHTML要素を作成
index.html
<body> <div> <p>ul要素の中にliタグを生成する。</p> <ul> </ul> </div> <script> $(function(){ const el = $('<li>', {id: 'created_li', class: 'created_li', text: 'liタグが生成されました。',}) $(el).appendTo($('ul')) }) </script> </body>
まずはli要素を作って変数に入れます。
const el = $('<li>', {id: 'created_li', class: 'created_li', text: 'liタグが生成されました。',})
$(要素, プロパティ)
としてli要素を作ります。何も難しいことはないですね!普通にhtmlのタグを書くようにそれぞれ指定してあげればいいだけです!
そうしたら表示したい箇所にappend!!
$(el).appendTo($('ul'))
$(作成した要素)
をappendTo(ここに表示したい!!)
el.appendTo($('ul'))
これでもいけますね。
これここで一回しか使わないんだったらわざわざ変数に入れる必要もないですよね。1行でやると
$('<li>', {id: 'created_li', class: 'created_li', text: 'liタグが生成されました。',}).appendTo($('ul'))
これでいけちゃいますね!
ちなみにみなさんjQueryの要素の指定は完璧ですかね?参考までにいくつか載せときますね
$('div') //タグで取得 $('.hoge') //クラスで取得 $('#fuga') //IDで取得 $('input[name="hogefuga"]') //特定のname属性がついたinput要素を取得
他にもいろんな取得方法があるので是非探して使ってみてください。
久々の投稿なので・・・
<!DOCTYPE html> <html lang='ja'> <head> <meta charset="utf-8"> <title>JavaScript Practice</title> <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script> </head> <style> </style> <body> <div> <p>ul要素の中にliタグを生成する。</p> <ul> </ul> <button id='asonjau'>久々だから遊んじゃう</button> </div> <script> $(function(){ //ボタンクリックで... $('#asonjau').on('click', function(){ //要素作成 const el = $('<li>', {id: 'created_li', class: 'created_li', text: 'liタグが生成されました。',}) //append!! $(el).appendTo($('ul')) }) }) </script> </body> </html>
ボタンと連携
今回はここまで
それではまた次回!
JavaScript input要素の操作・セレクトボックスの操作
JavaScript備忘録 Vol.15
目次
- input要素の操作
- セレクトボックスの操作
今回もJavaScriptの記事になっています。
input要素の操作
ここではinput要素に入力された値をリストに追加していきたいと思います。
index.html
<!DOCTYPE html> <html lang = 'ja'> <head> <meta charset="utf-8"> <title>JavaScript DOMPractice</title> </head> <body> <input type="text"> <button>追加</button> <ul> </ul> <script src='js/main.js'></script> </body> </html>
js/main.js
'use strict' { document.querySelector('button').addEventListener('click',() => { }) }
まずはli要素を作りましょう。
{ document.querySelector('button').addEventListener('click',() => { const li = document.createElement('li') }) }
document.createElement('li')
としてli要素を作ります。
次はinput要素に入力された値を取得します。
{ document.querySelector('button').addEventListener('click',() => { const li = document.createElement('li'); const text = document.querySelector('input'); li.textContent = text.value; }) }
querySelector('input')
としてinput要素を取得しtext
という定数に代入
input要素のvalue
をli
要素のtextに指定します。
あとはul要素にli要素を追加していけばいいですね。
{ document.querySelector('button').addEventListener('click',() => { const li = document.createElement('li'); const text = document.querySelector('input'); li.textContent = text.value; const ul = document.querySelector('ul'); ul.appendChild(li); }) }
ul要素を取得して、ul.appendChild(li)
としてul要素にli要素を追加していきます。
ブラウザは...
こんな感じです。
ただ、入力した文字が消えると尚いいですよね。
{ document.querySelector('button').addEventListener('click',() => { const li = document.createElement('li'); const text = document.querySelector('input'); li.textContent = text.value; const ul = document.querySelector('ul'); ul.appendChild(li); text.value = ''; text.focus(); }) }
text.value
に空文字を入力してあげて、ついでにinputにfocusする様にしましょう。
いい感じですね
ですが
今のままでは空文字も追加されてしまいます。
中身が空文字の時にはulに追加せず、alertを出しましょう。
{ document.querySelector('button').addEventListener('click',() => { const li = document.createElement('li'); const text = document.querySelector('input'); li.textContent = text.value; if(text.value !== ''){ const ul = document.querySelector('ul'); ul.appendChild(li); text.value = ''; }else{ alert('入力してください'); } text.focus(); }) }
こんな感じで条件分岐すればできますね。
セレクトボックスの操作
次はセレクトボックスを操作してみましょう。
index.html
<!DOCTYPE html> <html lang = 'ja'> <head> <meta charset="utf-8"> <title>JavaScript DOMPractice</title> </head> <body> <select> <option>マグロ</option> <option>サバ</option> <option>バナナ</option> </select> <button>追加</button> <ul> </ul> <script src='js/main.js'></script> </body> </html>
js/main.js
'use strict' { document.querySelector('button').addEventListener('click',() => { }) }
ブラウザはこんな感じです。
選択された値をリストに追加していきましょう。
まずはli要素を作っていきます。
{ document.querySelector('button').addEventListener('click',() => { const li = document.createElement('li'); }) }
さっきと同じですね。
次に選択された値を取得しましょう。
{ document.querySelector('button').addEventListener('click',() => { const li = document.createElement('li'); const food = document.querySelector('select'); li.textContent = `${food.value}:${food.selectedIndex}`; }) }
select
要素を取得しfood
という定数に代入
select要素の場合、value
と、selectedIndex
とすることでindex番号
も取得できるので、どちらも表示してみます。
あとはこれをul要素に追加していきましょう。
{ document.querySelector('button').addEventListener('click',() => { const li = document.createElement('li'); const food = document.querySelector('select'); li.textContent = `${food.value}:${food.selectedIndex}`; const ul = document.querySelector('ul'); ul.appendChild(li); }) }
この処理もさっきと一緒ですね。
また、select要素のvalueにはタグの中身が使われますが、別の値にしたい場合にはHTMLで指定することもできます。
<select> <option value='tuna'>マグロ</option> <option value='mackerel'>サバ</option> <option value='banana'>バナナ</option> </select>
結果は...
こうなります。
今回はここまで
次回は・・・まだまだJS!
それではまた次回!
JavaScript カスタムデータ属性、要素の追加・複製挿入・削除
JavaScript備忘録 Vol.14
目次
- カスタムデータ属性
- 要素の追加
- 要素の複製・挿入
- 要素の削除
今回もJavaScriptの記事になっています。
カスタムデータ属性
まずは最初の段階のindex.htmlとmain.jsの中身です
index.html
<!DOCTYPE html> <html lang = 'ja'> <head> <meta charset="utf-8"> <title>JavaScript DOMPractice</title> </head> <body> <h1 id='target'>プログラマー</h1> <p>JavaScript.JavaScript.JavaScript.</p> <p>React.React.React.</p> <p>JQuery.JQuery.JQuery.</p> <button id='btn'>Button</button> <script src='js/main.js'></script> </body> </html>
js/main.js
'use strict' { function upDate(){ const target = document.getElementById('target'); } const btn = document.getElementById('btn'); btn.addEventListener('click', () => { upDate(); }) }
ではまず、h1の値を英語で出力してみます
function upDate(){ const target = document.getElementById('target'); target.textContent = 'Programer'; }
target.textContent
としてProgramer
を出力してあげる処理ですね。
ここで
この英訳するという処理ですが、こんな書き方もできます。
HTMLでは、'data-'から始めることで独自の属性をつける
ことができます。
今回の場合だと...
<h1 id='target' data-transration='Programer'>プログラマー</h1>
と書きます。
これをJavaScriptで操作するには...
target.textContent = target.dataset.translation;
この様に書いてあげればOKです。
target.textContent = target.data-translation;
とは書かないことに注意しましょう。
要素の追加
次は要素を追加する方法をみていきましょう。
最初はこんな感じ
<!DOCTYPE html> <html lang = 'ja'> <head> <meta charset="utf-8"> <title>JavaScript DOMPractice</title> </head> <body> <ul> <li>li 0</li> <li>li 1</li> </ul> <button id='btn'>Button</button> <script src='js/main.js'></script> </body> </html>
'use strict' { function upDate(){ } const btn = document.getElementById('btn'); btn.addEventListener('click', () => { upDate(); }) }
- 新たにli要素を作る
- li要素の中身のテキストを作る
- 親要素に対し、子要素の末尾に追加する
この手順でやっていきます。
まずは完成版
'use strict' { function upDate(){ const li2 = document.createElement('li'); li2.textContent = 'li 2'; const ul = document.querySelector('ul'); ul.appendChild(li2); } const btn = document.getElementById('btn'); btn.addEventListener('click', () => { upDate(); }) }
細かく見ていきましょう
1.li要素を作る
const li2 = document.createElement('li');
createElement('li')
とすることでli要素を作り、li2
という定数に入れます。
2.li要素の中身のテキストを作る
li2.textContent = 'li 2';
textContent
として中身のテキストをli 2
とします。
3.親要素に対し、子要素の末尾に追加する
最後に親要素に追加するのですが、いくつか手順を踏みます。
const ul = document.querySelector('ul');
document.querySelector('ul')
として、ul要素を取得し、ul
という定数に代入します。
ul.appendChild(li2);
ul.appendChild(li2)
とすることで親要素のul
の子要素末尾
にli2
を追加することができます。
要素の複製・挿入
次は要素を複製して任意の場所に挿入する方法を見ていきましょう。
HTMLには li 2 を追加し
<!DOCTYPE html> <html lang = 'ja'> <head> <meta charset="utf-8"> <title>JavaScript DOMPractice</title> </head> <body> <ul> <li>li 0</li> <li>li 1</li> <li>li 2</li> </ul> <button id='btn'>Button</button> <script src='js/main.js'></script> </body> </html>
JavaScriptはこんな状態
'use strict' { function upDate(){ } const btn = document.getElementById('btn'); btn.addEventListener('click', () => { upDate(); }) }
現在の画面はこんな感じですね。
今回は li 0 をコピーして li 2 の前に挿入したいと思います。
手順は
- li 0をコピー
- コピーした li 0 を li 2 の前に追加
完成版
'use strict' { function upDate(){ const li0 = document.querySelectorAll('li')[0]; const copy = li0.cloneNode(true); const ul = document.querySelector('ul'); const li2 = document.querySelectorAll('li')[2]; ul.insertBefore(copy, li2); } const btn = document.getElementById('btn'); btn.addEventListener('click', () => { upDate(); }) }
見ていきましょう。
1.li 0をコピー
const li0 = document.querySelectorAll('li')[0];
querySelectorAll('li')
でli
要素を全て取得し[0]として0番目を指定し、li0
という定数に代入します。
const copy = li0.cloneNode(true);
cloneNode(true)
とすることでli.0をコピーし、copy
という定数に代入します。
ちなみにcloneNode(false)
とすると空のli要素が作られます。
2.コピーした li 0 を li 2 の前に追加
const ul = document.querySelector('ul'); const li2 = document.querySelectorAll('li')[2];
まずは今までと同じ様に、ul要素とli要素の2番目を取得します。
ul.insertBefore(copy, li2);
insertBefore(何を,どこに)
とすることで挿入することができます。
今回の場合は
ul
要素のli2
の直前にcopy
を挿入するといった処理ですね。
要素の削除
次は要素を削除する方法を見ていきましょう。
HTMLはそのまま、JavaScriptは元に戻します。
'use strict' { function upDate(){ } const btn = document.getElementById('btn'); btn.addEventListener('click', () => { upDate(); }) }
削除は簡単
今回は li 1 を消してみます。
function upDate(){ const li1 = document.querySelectorAll('li')[1]; li1.remove(); }
定数li1
として要素を取得し、remove( )
としてあげるだけです。
また
一部のブラウザではこの方法が使えない場合もあるので
function upDate(){ const li1 = document.querySelectorAll('li')[1]; const ul = document.querySelector('ul'); ul.removeChild(li1); }
親Node.removeChild(削除するNode)
とする書き方もあります。
どちらも覚えておくといいかもしれませんね。
今回はここまで
次回は・・・まだまだJS!
それではまた次回!