男子プログラマーになりたいやつ

未経験から一端のエンジニア目指し日々勉強中です。

MERN client行ってみよう

MERN行ってみる? f:id:TomozQ:20220212185303j:plain

MERN client準備編

目次




前回の続きです。

今回はクライアントの処理を書いていきます。


今回作成していくもの

f:id:TomozQ:20220206134727g:plain

コンポーネントの雛形作成

ターミナルでclientに移動してパッケージをインストールします

% cd client
% npm install @material-ui/core

次にclientフォルダー直下にcomponentsフォルダーを作成して

さらにその下にフォルダーを作っていきます。

Formフォルダーを作成し、その中にForm.jsファイルを作成

Postsフォルダーを作成し、その中に Posts.jsファイルを作成

PostsフォルダーにPostフォルダーを作成し、その中にPost.jsファイルを作成します。

f:id:TomozQ:20220212122630p:plain

次に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'

現状このように画面が表示されています。

スタイルは当ててないので画像は変な感じになってると思います。

f:id:TomozQ:20220212122648p:plain

スタイル適応の準備

スタイルを当てていきます。

まずは各フォルダーに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

f:id:TomozQ:20220212124105p:plain

次に各ファイルの中身を書いていきます。

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;

ややこしくなってきたので一旦図でまとめてみました。

間違ってたら教えてください・・・

f:id:TomozQ:20220212182745p:plain

長くなってきたので今回はここまでにします。

現在のclientのフォルダ構成はこんな感じになってると思います。

f:id:TomozQ:20220212183420p:plain

次回も引き続きクライアント側の表示/投稿処理を実装していきます。



今回はここまで

続きは次回!

それではまた!

MERN serverセットアップ

MERN行ってみる? f:id:TomozQ:20220211210318j:plain

MERN Server処理準備編

目次
  • routeの作成
  • controllerの作成
  • modelの作成
  • server/一覧表示・投稿処理の作成




前回の続きです。

今回はサーバーの処理を書いていきます。


今回作成していくもの

f:id:TomozQ:20220206134727g:plain

routeの作成

まずはserverディレクトリにroutesというディレクトリを作成します。

その中にposts.jsを作成します。

f:id:TomozQ:20220211192639p:plain

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にアクセスすると下のような画面が表示されるかと思います。 f:id:TomozQ:20220211192716p:plain

次に機能を実装する前にフォルダ構成を整えていきます。

controllerの作成

まずserver直下にcontrollersディレクトリを作成し、その中にposts.jsを作成します。

f:id:TomozQ:20220211202620p:plain

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を作成します。

f:id:TomozQ:20220211202635p:plain

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にアクセスすると空の配列が返ってきます。これはまだ投稿データがないためです。

f:id:TomozQ:20220211202406p:plain

次に投稿処理を簡単に実装します。

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ステータスコードについて詳しく知りたい方は下記にアクセスしてみてください。

HTTP Status Codes

ざっくりだと

  • 200番台

    成功

  • 300番台

    リダイレクト

  • 400番台

    クライアントエラー

  • 500番台

    サーバーエラー

という感じになっているようです。

これでserver側の基本的な一覧表示と投稿処理ができました。

次回はクライアント側の投稿処理を実装していきます。



今回はここまで

続きは次回!

それではまた!

MERN環境構築

MERN行ってみる? f:id:TomozQ:20220206190716j:plain

MERN環境構築編

目次
  • 参考動画
  • 環境構築




今回からMERNスタックについて書いていきます。


MERNとは

  • MongoDB
  • Express
  • React
  • Node

の略です。これらを使用して簡単なアプリケーションを作っていきます。

今回学習に使用させていただいた動画がこちら

MERNについては英語の記事多め、動画もUdemyも英語ばっかり

自分自身もUdemyに日本語対応している講座がなくて、この動画を見て勉強させてもらいました。

この動画を見ながらGoogle先生が翻訳して字幕を出してくれるのですが・・・

んーわからない!

それでもなんとかアプリ自体は作れましたので

自分の備忘録として何回かに渡って進め方を書いていこうと思います。

英語にアレルギーがある方はぜひ参考にしていただければと思います。

まあ余裕っしょって方は上記の動画を参考に

今回作成していくもの

f:id:TomozQ:20220206134727g:plain

環境構築

まずは任意の場所にフォルダーを作成します。

f:id:TomozQ:20220206141327j:plain

今回はデスクトップに「memories101」というフォルダーを作成し、vscodeでそのフォルダーを開きます。

f:id:TomozQ:20220206141403p:plain

クライアント用とサーバー用にターミナルを二つ開きます。

memories101直下にclientディレクトリ、serverディレクトリを作成します。

f:id:TomozQ:20220206141421p:plain

先ほど開いたターミナルでそれぞれのディレクトリに移動します。

% cd client
% cd server

f:id:TomozQ:20220206141918p:plain

client側でReactをインストールします。

前提としてNode.jsのLTSをインストールしといてください。

% npx create-react-app ./

f:id:TomozQ:20220206142633p:plain

serverディレクトリ直下にindex.jsファイルを作成します。

f:id:TomozQ:20220206142648p:plain

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ディレクトリを作成します。

f:id:TomozQ:20220206145724p:plain

新たに作成したsrc直下にindex.jsファイルを作成します。

f:id:TomozQ:20220206145736p:plain

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

こんな画面が表示されます。

f:id:TomozQ:20220206150926p:plain

続いてサーバー側のセットアップをしていきます。

今回DBはmongoDB Atlasを使用していきます。

まずはDBを作成していきます。

mongodb.comにアクセスし、Try Freeをクリック

f:id:TomozQ:20220206170509p:plain

使用目的っぽいアンケートをテキトーに埋める

f:id:TomozQ:20220206170538p:plain

プライバシーポリシーと規約に同意してsubmit

f:id:TomozQ:20220206170522p:plain

sharedというのが無料なので、これを選択し、Create Cluster

f:id:TomozQ:20220206170555p:plain

3~5分くらいかかるよーと言われるので

f:id:TomozQ:20220206171435p:plain

その間にDB使用ユーザーを作成する

左のメニューバーのDatabase Accessをクリック

Add New Database Userをクリック

f:id:TomozQ:20220206171703p:plain

赤枠上段に任意のユーザー名、下段にパスワードを入力する。

f:id:TomozQ:20220206173615p:plain

Add Userをクリック

f:id:TomozQ:20220206174807p:plain

次にネットワークを追加します。

左のメニューバーのNetwork Access→Add IP Address

f:id:TomozQ:20220206173644p:plain

Add Current IP Address

Access List Entryという部分に自動でIPが入力されるので、confirm

f:id:TomozQ:20220206173659p:plain

ここがpendingになって

f:id:TomozQ:20220206174145p:plain

Active

f:id:TomozQ:20220206174126p:plain

左のメニューバーのDatabases→Connect→Connect Your Application

f:id:TomozQ:20220206175746p:plain

Copy

f:id:TomozQ:20220206174200p:plain

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と接続できています。

f:id:TomozQ:20220206181632p:plain

これで基本的な環境構築はできました。

次回からは本格的にコードを書き始めます。



今回はここまで

続きは次回!

それではまた!

children().children()とかやってないよね?

<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a> f:id:TomozQ:20210821115046j:plain

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>

f:id:TomozQ:20210821114543g:plain

find()で要素を探すことができます。

find('div')
find('.class')
find('#id')

こんな探し方もできるのでやってみてください!


今回はここまで

それではまた次回!

jQueryでHTML要素を作成

<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a> f:id:TomozQ:20210821104100j:plain

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>

f:id:TomozQ:20210821101239p:plain

まずはli要素を作って変数に入れます。

const el = $('<li>', {id: 'created_li', class: 'created_li', text: 'liタグが生成されました。',})


$(要素, プロパティ)としてli要素を作ります。何も難しいことはないですね!普通にhtmlのタグを書くようにそれぞれ指定してあげればいいだけです!


そうしたら表示したい箇所にappend!!

$(el).appendTo($('ul'))

$(作成した要素)appendTo(ここに表示したい!!) f:id:TomozQ:20210821101254p:plain

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>

ボタンと連携

f:id:TomozQ:20210821103310g:plain


今回はここまで

それではまた次回!

JavaScript input要素の操作・セレクトボックスの操作

<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a> DOM編 vol.4 f:id:TomozQ:20201117215135j:plain

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',() => {
    
  })
}

f:id:TomozQ:20201117214513p:plain

まずは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要素のvalueli要素の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要素を追加していきます。

ブラウザは...

f:id:TomozQ:20201117214449g:plain

こんな感じです。


ただ、入力した文字が消えると尚いいですよね。

{
  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する様にしましょう。 f:id:TomozQ:20201117214428g:plain

いい感じですね

ですが

今のままでは空文字も追加されてしまいます。

f:id:TomozQ:20201117214411g:plain

中身が空文字の時には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();
  })
}

こんな感じで条件分岐すればできますね。

f:id:TomozQ:20201117214348g:plain


セレクトボックスの操作

次はセレクトボックスを操作してみましょう。

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',() => {
    
  })
}

ブラウザはこんな感じです。

f:id:TomozQ:20201117214331g:plain

選択された値をリストに追加していきましょう。




まずは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);
  })
}

この処理もさっきと一緒ですね。

f:id:TomozQ:20201117214314g:plain

また、select要素のvalueにはタグの中身が使われますが、別の値にしたい場合にはHTMLで指定することもできます。

<select>
  <option value='tuna'>マグロ</option>
  <option value='mackerel'>サバ</option>
  <option value='banana'>バナナ</option>
</select>

結果は...

f:id:TomozQ:20201117214257g:plain

こうなります。






今回はここまで

次回は・・・まだまだJS!

それではまた次回!

JavaScript カスタムデータ属性、要素の追加・複製挿入・削除

<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a> DOM編 vol.3 f:id:TomozQ:20201116221020j:plain

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();
  })
}

f:id:TomozQ:20201116220127p:plain

ではまず、h1の値を英語で出力してみます

function upDate(){
  const target = document.getElementById('target');
  target.textContent = 'Programer';
}

f:id:TomozQ:20201116220042g:plain target.textContentとしてProgramerを出力してあげる処理ですね。

ここで

この英訳するという処理ですが、こんな書き方もできます。


HTMLでは、'data-'から始めることで独自の属性をつけることができます。

今回の場合だと...

<h1 id='target' data-transration='Programer'>プログラマー</h1>

と書きます。

これをJavaScriptで操作するには...

target.textContent = target.dataset.translation;

この様に書いてあげればOKです。

target.textContent = target.data-translation;

とは書かないことに注意しましょう。

f:id:TomozQ:20201116220042g:plain


要素の追加

次は要素を追加する方法をみていきましょう。

最初はこんな感じ

<!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();
  })
}

f:id:TomozQ:20201116220113p:plain

  1. 新たにli要素を作る
  2. li要素の中身のテキストを作る
  3. 親要素に対し、子要素の末尾に追加する

この手順でやっていきます。

まずは完成版

'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を追加することができます。
f:id:TomozQ:20201116220021g:plain


要素の複製・挿入

次は要素を複製して任意の場所に挿入する方法を見ていきましょう。

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();
  })
}

現在の画面はこんな感じですね。 f:id:TomozQ:20201116220102p:plain

今回は li 0 をコピーして li 2 の前に挿入したいと思います。

手順は

  1. li 0をコピー
  2. コピーした 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);

f:id:TomozQ:20201116220003g:plain
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( )としてあげるだけです。 f:id:TomozQ:20201116215949g:plain

また

一部のブラウザではこの方法が使えない場合もあるので

function upDate(){
  const li1 = document.querySelectorAll('li')[1];
  const ul = document.querySelector('ul');

  ul.removeChild(li1);
}

親Node.removeChild(削除するNode)とする書き方もあります。

どちらも覚えておくといいかもしれませんね。






今回はここまで

次回は・・・まだまだJS!

それではまた次回!