20200520のHTMLに関する記事は16件です。

PHP&MySQLでデータの個数を数える方法(PDO)

MySQL接続をした後この処理をします。

$sql_form = "SELECT * FROM テーブル名";
$sql_form_result = $PDO -> query($sql_form);
$form_row_count = $sql_form_result->rowCount();

変数の名前は必要に応じて変えても大丈夫です。
$form_row_countという変数にデータ数が格納されています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPでデータベースの重複を取得するには

<?php
$query = $dbh->query("SELECT COUNT(*) FROM formdata WHERE userid = '".$userid."' AND kind = '".$kind."'");
$count = $query->fetchColumn();
if ($count > 0){
?>
<p align="center">投稿が重複しています</p>
<?php
}else{
// データの追加
$sql = 'INSERT INTO formdata(id, kind, star, message, userid) VALUES("'.$id.'","'.$kind.'","'.$star.'","'.$message.'","'.$userid.'")';
$stmt = $dbh -> prepare($sql);
$stmt -> execute();
?>
<p align="center">投稿ありがとうございました。</p>

mysqli接続だとfetchColumやprepare関数が使えなくなるのでpdo接続してあります。

2行目は
formdataというテーブルの中に
kindというフィールドがphpの変数kindと同じかつ、useridというフィールドがphpの変数useridと同じデータが
何個あるかカウントしています。

4行目のif文で、カウントした個数が0よりも多かった場合に重複した時の処理を出力します。
(ここではhtmlのテキストを出力)

10行目では、データが重複しなかったので新たなデータをデータベースに追加します。
id, kind, star, message, useridは追加するデータのフィールド名

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

phpでひとつ前のページにリダイレクトする方法

header('Location: '.$_SERVER['HTTP_REFERER']);
exit;

リダイレクトで処理が中断されるのでexit;を書いておきましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPでひとつ前のページにリダイレクトする方法

header('Location: '.$_SERVER['HTTP_REFERER']);
exit;

リダイレクトで処理が中断されるのでexit;を書いておきましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

onclickを用いて複数の関数を呼び出す

Onclickで複数の関数を記述する

初心者プログラマーの備忘録です。

記法1:関数をセミコロン(;)で区切る

input type = "XXX" value = "a" onclick = "YYY;ZZZ"
このように、関数をセミコロンで区切って記述した場合、YYY → ZZZの順に関数を実行。
仮に YYY = true, ZZZ = false であっても、XXXが実行される。
YYY = false, ZZZ = true の場合は、YYYの結果ではじかれるためXXXは実行されない。

記法2:関数をカンマ(,)で区切る

input type = "XXX" value = "a" onclick = "YYY, ZZZ"
基本的にカンマで関数を区切ることはないが、上記のように記述した場合
カンマの右側の関数(ZZZ)の結果が true であれば、YYYの結果に依らずXXXが実行される。

記法3:関数を「&&」で区切る

input type = "XXX" value = "a" onclick = "YYY && ZZZ"
このように記述した場合、関数 YYY および ZZZ の結果がともに true であれば、XXXが実行される。

おまけ

まだ試していないが、仮に
input type = "XXX" value = "a" onclick = "YYY || ZZZ"
とすれば、YYYあるいはZZZのどちらかの結果が true であれば、XXXが実行されると考えられる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

乱出するCTAリンクの更新にイライラしているLP更新者の方への提案

LPあるある

1ページ中に同じお問い合わせエリア(CTAボタンやら電話番号やら)が複数回でてくる

例えばこんな感じ

LP/index.html:before
<body>
  <section id="sec1">
    <div><p>内容1</p></div>
  </section>
  <div class="cta">
    <div class="tel">
      <a href="tel:0123456789">0123-45-6789</a>
    </div>
    <div class="link">
      <a href="//google.com"><div class="button">お問い合わせはこちら</div></a>
    </div>
  </div>
  <section id="sec2">
    <div><p>内容2</p></div>
  </section>
  <div class="cta">
    <div class="tel">
      <a href="tel:0123456789">0123-45-6789</a>
    </div>
    <div class="link">
      <a href="//google.com"><div class="button">お問い合わせはこちら</div></a>
    </div>
  </div>
  <section id="sec3">
    <div><p>内容3</p></div>
  </section>
  <div class="cta">
    <div class="tel">
      <a href="tel:0123456789">0123-45-6789</a>
    </div>
    <div class="link">
      <a href="//google.com"><div class="button">お問い合わせはこちら</div></a>
    </div>
  </div>
</body>

「どんだけ、お問い合わせエリアで場所とってんねん:rage:」って気分になる
視認性も良くない

さらに「計測用のクリックイベントを追加して」「電話番号が変わりました」なんて修正依頼もあったり...

いちいち検索して手作業もたいへんだし
エディタで一括置換もできるけど、本当にちゃんと出来てるかも不安だし...

なんとか1箇所の変更で済むようにしたい(一括編集したい)

JSに頼ろう

こんな感じにして解決 (JavaScript で HTML を書き換え)

LP/index.html:after
<body>
  <section id="sec1">
    <div><p>内容1</p></div>
  </section>
  <div class="cta"></div> <!-- ← ココにお問い合わせ表示 -->
  <section id="sec2">
    <div><p>内容2</p></div>
  </section>
  <div class="cta"></div> <!-- ← ココにお問い合わせ表示 -->
  <section id="sec3">
    <div><p>内容3</p></div>
  </section>
  <div class="cta"></div> <!-- ← ココにお問い合わせ表示 -->
</body>

<!-- 表示させるお問い合わせのコード -->
<script id="cta_code" type="text/html">
  // ココから
  <div class="tel">
    <a href="tel:0123456789">0123-45-6789</a>
  </div>
  <div class="link">
    <a href="//google.com"><div class="button">お問い合わせはこちら</div></a>
  </div>
  // ココまで
</script>
<!-- END 表示させるお問い合わせのコード -->

<!-- .cta にコードを入れるスクリプト -->
<script type="text/javascript">
  var code = document.getElementById("cta_code").innerHTML; // 上記の「表示させるお問い合わせのコード」がつまった #cta_code を格納
  var cta = document.querySelectorAll(".cta"); // ソース中から .cta を見つけて格納
  var arr = Array.prototype.slice.call(cta); // forEach が使えるように配列に
  arr.forEach(function (e) {
    e.innerHTML = code; // 入れ替え実施
  });
</script>
<!-- END .cta にコードを入れるスクリプト -->

解説

1)お問い合わせエリアに

お問い合わせを入れたい部分に<div class="cta"></div>を入れる

2)表示させるお問い合わせのコード

// ココから // ココまで の間に書き換えたいHTMLを置く

ポイントは<script id="cta_code" type="text/html">の部分
type="text/html"で、表には表示させないように。

<div id="cta_code" style="display:none">でも動くと思うけど、どちらでも)

3).cta にコードを入れるスクリプト

  • Array.forEach()を使いたい
  • IE11でも動くようにしたい

ということからArray.prototype.slice.call()を使うことに

参考サイト:IEで NodeList を forEach するとエラーになる問題の対処方

解決 :relaxed:

これで、今後に更新があっても、1箇所だけの修正で対応できます

image.png

↑ レンダリングされたあとは冒頭のLP/index.html:beforeと同じソースになってる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PC版ではロゴと検索窓が出て、スマートフォン版では切り替え表示したいなと思ったら・・・

タイトルの通りですが、PC版では検索窓とサイトのロゴを出したいけど、スマホ版ではどちらも出す余裕はありませんが、ハンバーガーデザインに分けることもしたくなかったので作ってみました

 コードとデモ

デモ

https://jsfiddle.net/mqgc207L/

コード

CSS部

    @media screen and (max-width: 768px) {
      .SearchWindow__view {
          display: none;
      }
    }

サンプルではBootstrap4を使っていることもあり、今回は768pxを区分けしましたが、検索窓に張り付けるクラスをとりあえずスマホとPC版を切り替えたいブレークポイントで非表示と表示に切り替えるようにします。

JS部

const SMP_SEARCH  = document.getElementById("SearchWindow");
  const SMP_LOGO    = document.getElementById("LogoWindow");
  const SMP_LINK    = document.getElementById("header__btm--icon");
  const CLS_SEARCH  = 'fas fa-search';
  const CLS_CROSS   = 'fas fa-times';
  const WINDOWS_MD  = 768;
  let flgChenge     = true;

  window.addEventListener('resize', function(e) {
    //現在のサイズを取得
    let nowsize = window.innerWidth;
    if( (nowsize >= WINDOWS_MD)  ){
      //基準以上ならリセット
      display_reset();
      SMP_SEARCH.style.display ="";
    }
  });

  function clickBtn1(){
    if(flgChenge){
      // 検索窓表示
      SMP_LINK.className = CLS_CROSS;
      $(SMP_LOGO).hide();
      $(SMP_SEARCH).show();
      $(SMP_SEARCH).removeClass('SearchWindow__view');
      flgChenge = false;
    }else{
      // 検索窓非表示
      display_reset();
    }
  } 

  function display_reset(){
    SMP_LINK.className = CLS_SEARCH;
    $(SMP_LOGO).show();
    $(SMP_SEARCH).hide();
    $(SMP_SEARCH).addClass('SearchWindow__view');
    flgChenge = true;
  }

起動時にフラグ用引数を用意し、ボタンを操作する度にclickBtn1関数を呼び出して表示・商事を繰り返しますが、PC版ではリセットする必要があるので、 window.addEventListener('resize', function(e) {});でリサイズ時のサイズを算定。所定以上ならリセットを行います。なお、display: block;が残っていると拡大→縮小を繰り返すと最初は隠しておくべき検索窓が表示されるので、SMP_SEARCH.style.display ="";で消しておきます。

<header id="header">
  <div class="row" id="header__top">
    <div id="LogoWindow" class="col-md-4 col-12">
      <h1><a href="#">LOGO</a></h1>
    </div>
    <div id = "SearchWindow" class="col-md-8 col-12 SearchWindow__view">
      <form id="header__search" action="/" method="get">
        <input class="validate" name="search" type="text" autocomplete="off" placeholder="キーワードを入力" >
        <button type="submit">検索</button>
      </form>
    </div>
  </div>

  <!--ボタン-->
  <div id="header__btm">
    <div class="d-block d-md-none">
      <a href="#" class="text-grey darken-4" onclick="clickBtn1()">
      <i id="header__btm--icon" class="fas fa-search" style="font-size:2.0rem;"></i></a>
    </div>
  </div>

HTMLの本文です。画像サイズによって表示するかどうかを区分けするのは難しく車輪の差発明になるので、ここではBootstrapの表示ユーティリティを多用しています。グリッドシステムのみのCSSが入ったBootsrap Gridにもこのユーティリティは附属しているので活用して頂ければと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

herokuでLPを無料で公開する方法

この記事について

htmlファイルをherokuでデプロイしようと思った時、あれ?できない。。。となったので備忘録として手順を振り返りつつ残しておきたいので記事にしました。

参考記事

・HTMLページをHerokuにデプロイ
https://qiita.com/Hai-dozo/items/f0829dd121f477754b98
こちらの記事はとてもわかりやすく書いてます。

開発環境

・Mac Pro
・Herokuアカウントがあること
・PHPがローカルにインストールされていること
・Composerがローカルにインストールされていること
・githubにファイル登録済み

1.自分のLPファイルにindex.php,package.jsonを追加 以下の内容を入れておく

index.php
<?php include_once("index.html"); ?>
package.json
{}

2.herokuにログイン

heroku login

3.herokuでアプリを作成するか追加する、その後確認

heroku create アプリ名 or git remote add heroku 作成したherokuアプリのurl
git remote -v

origin と herokuが作成されていたら完了です。

4.gitとherokuにpushする

git add .
git commit -m "コメント"
git push origin master
git push heroku master

5.herokuにデプロイされたか確認

heroku ps:scale web=1
heroku open

これで画面が正常にでたら完了です。

6.最後に

以上がhtmlファイルをherokuにアップする備忘録でした。
デプロイ作業はどこがミスしてるかわかりにくいので振り返りに使おうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リンクの中にリンクを入れたい時は?

リンクの中にリンクを入れたいレイアウト

aタグの中にaタグ

こんなレイアウ見たことありますよね?

業務でこんなレイアウトで実装しなきゃいけなくて、どうやるか色々と調べたので、まとめようと思います。

aタグの中にaタグを設置して見る

sample.html
<a>
<p>
   <a>リンク</a>
</p>
</a>

にしてみると
aタグの中にaタグ

とレイアウトが、崩れてしまいました。

対策1:Objectタグで囲む

sample.html
<a>
<p>
   <object><a>リンク</a></object>
</p>
</a>

objectタグとは?

HTML の 要素は、画像、内部の閲覧コンテキスト、プラグインによって扱われるリソースなどのように扱われる外部リソースを表現します。
リファレンス

属性は、HTML5で廃止されたものも多いので注意です。
主要なブラウザには対応しているので、使えそうですね、、、。

対策2:JavaScriptのclickイベントを使う

sample.html
<a>
<p>
   <span data-url="/link" class="js-click">リンク</span>
</p>
</a>
$('.js-click').on('click', function(event){
  //伝播をストップ
  e.stopPropagation();
  e.preventDefault();

  //リンクを取得して飛ばす
  location.href = $(this).attr('data-url');
})

引用
ここの実装は、実装環境にもよるので、引用させてもらいました。
location.href を使うって感じです。

SEOは大丈夫?

googleサイトをみる限り、jsを読んでくれますが、イベントで生成されるリンクまでを読んでくれるかは不確かです。
調べてみると
- https://www.suzukikenichi.com/blog/content-and-link-generated-by-javascript-are-treated-just-same-as-static-content-and-link/
- https://www.suzukikenichi.com/blog/google-can-read-javascript-and-pass-pagerank-and-anchor-text/
- https://webtan.impress.co.jp/e/2019/10/07/34043#moz16
という記事もあり、レンダリングされるようなリンクであれば読み取ってくれそうですが、、、。
「local.href」はわからないです。

aタグの中にaタグを書くのはNG×

リファレンスを読むと許可されている親要素に

記述コンテンツを受け入れるすべての要素、フローコンテンツ を受け入れるすべての要素。ただし 要素を除く。

と書いてあります。
aタグ内でaタグを書くのはよくなさそうですね、、、

結局リンクの中にリンクを入れたい時は?

  • 最初にレイアウトの変更を考える

のがいいかなーって思います。

リンクの中にリンクをいれると、ユーザが間違ってクリックしてしまう、間違ってタップしてしまう可能性も高いですしね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

マイライブラリ:html基本構造

<!DOCTYPE html>
<html lang="ja">
  <head>
  </head>
  <body>
      </body>
</html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

マイライブラリ:ベースのhtmlファイル

基本構造

headの記述

<head>
    <meta charset="UTF-8">
    <title>HTML文書の基本</title>
    <link rel="stylesheet" href="https://unpkg.com/ress/dist/ress.min.css">
    <link rel="stylesheet" href="css/style.css">
    <meta name="description" content="文書の説明は検索エンジンの検索結果ページに表示されるため、タイトルと並びSEO上非常に重要です。">
</head>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

マイライブラリ:headの記述

headの記述

〇基本セット

<head>
    <meta charset="UTF-8">
    <title>HTML文書の基本</title>
    <link rel="stylesheet" href="https://unpkg.com/ress/dist/ress.min.css">
    <link rel="stylesheet" href="css/style.css">
    <meta name="description" content="文書の説明は検索エンジンの検索結果ページに表示されるため、タイトルと並びSEO上非常に重要です。">
</head>

〇必要に応じて追加

・googleフォント https://fonts.google.com/
フォントを選んでEmbedでソースをコピーして貼り付ける

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

フォームをGETで送信するときは送信したいパラメータをURLではなくhiddenタグに設定する必要がある、という話

はじめに:イントロダクション

以下のような単純なRailsのフォームがあったとします。

<%= form_tag foo_blogs_path(some_flag: 1) do %>
  <%= button_tag 'Foo' %>
<% end %>

コントローラのコードは次のようにsome_flagの値をnoticeに出力するようになっています。

class BlogsController < ApplicationController
  def foo
    redirect_to :blogs, notice: "Foo / some_flag: #{params[:some_flag]}"
  end
end

以下はFooボタンをクリックしたときの実行結果です。
フォームのURLに設定したsome_flag: 1の値が表示されています。

Screen Shot 2020-05-20 at 9.27.10.png

本題:困ったこと

上の例と同じようなことを以下のようなフォームでもやろうとしました。

<%= form_tag bar_blogs_path(some_flag: 1), method: :get do %>
  <%= button_tag 'Bar' %>
<% end %>

先ほどのコード例と違うのはフォームのHTTPメソッドがGETになっている点(method: :get)です。

コントローラ側のコードはほぼ同じです。

class BlogsController < ApplicationController
  def bar
    redirect_to :blogs, notice: "Bar / some_flag: #{params[:some_flag]}"
  end
end

しかし、Barボタンをクリックしてみると・・・

Screen Shot 2020-05-20 at 9.27.30.png

あれっ、some_flagの値が空になってる!

ログを見るとこんなふうになっていてsome_flagの値が渡されていません。

Started GET "/blogs/bar?button=" for 127.0.0.1 at 2020-05-20 09:13:49 +0900

出力されたHTMLを見てみると、action="/blogs/bar?some_flag=1"のようにsome_flagの値がちゃんと設定されているように見えます。

<form action="/blogs/bar?some_flag=1" accept-charset="UTF-8" method="get">
  <button name="button" type="submit">Bar</button>
</form>

なんでだろう、おかしいなあ・・・。
原因を突き止めるためにいろいろ試行錯誤したものの、some_flagの値をサーバーに送信することができず、この日は諦めて寝ることにしました。

翌日・・・解決しました!

次の日、デバッグを再開したところ、今度は原因と解決策がわかりました。
フォームをGETで送信する場合は、actionのURLではなくhiddenタグに送信したいパラメータを含める必要があるのでした。

<%= form_tag bar_blogs_path, method: :get do %>
  <!-- hiddenタグに送信したいパラメータを含める -->
  <%= hidden_field_tag :some_flag, 1 %>
  <%= button_tag 'Bar' %>
<% end %>

こうすればsome_flagの値をサーバーに送信することができます!

Screen Shot 2020-05-20 at 9.27.45.png

ログを見てもsome_flag=1が送信されていることがわかります。

Started GET "/blogs/bar?some_flag=1&button=" for 127.0.0.1 at 2020-05-20 09:22:21 +0900

これで解決です。めでたしめでたし。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者によるプログラミング学習ログ 321日目

100日チャレンジの321日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
321日目は、

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vue.jsとlocalStrageで閲覧履歴とお気に入り履歴を作ってみた

やったこと

ユーザの閲覧履歴やお気に入り履歴をlocal Strageに溜め込んでブラウザ側だけで履歴情報を表示するページを作りました。
中の処理ではVue.jsを使っています。

使っているもの / できること

動いているページ
http://shima-07.ml/

image.png

ソースコード

<html>
  <head>
    <title>Hello My WebSite!</title>
    <style>
        img.pic1 {
         width: 50%;
         height: auto;
         }
    </style>
    <style>
       img.pic2 {
        width: 96px;
        height: 65px;
        }
    </style>
  </head>

  <body>

    <div id= "app">
        <a v-bind:href="src" target="_blank">  <img v-bind:src="src"  class="pic1"/> </a>
        <p><button v-on:click="getData()">次へ</button></p>
        <p>
            <button v-if="good" v-on:click="delfavo()">お気に入りから削除する</button>
            <button v-else v-on:click="favo()">お気に入りに追加する</button>
        </p>


        <p>最大5件まで過去閲覧画像を表示</p> 
        <!-- 画像URLが存在するときのみ表示する-->
        <a v-bind:href="his_1" target="_blank"> <img v-if="his_1" v-bind:src="his_1" class="pic2"/>  </a>
        <a v-bind:href="his_2" target="_blank"> <img v-if="his_2" v-bind:src="his_2" class="pic2"/> </a>
        <a v-bind:href="his_3" target="_blank" > <img v-if="his_3" v-bind:src="his_3" class="pic2"/> </a>
        <a v-bind:href="his_4" target="_blank" > <img v-if="his_4" v-bind:src="his_4" class="pic2"/> </a> 
        <a v-bind:href="his_5" target="_blank" > <img v-if="his_5" v-bind:src="his_5" class="pic2"/> </a>

        <p>お気に入りのわんちゃんを表示</p> 
        <!-- 画像URLが存在するときのみ表示する-->
        <a v-bind:href="fav_1" target="_blank"> <img v-if="fav_1" v-bind:src="fav_1" class="pic2"/>  </a>
        <a v-bind:href="fav_2" target="_blank"> <img v-if="fav_2" v-bind:src="fav_2" class="pic2"/> </a>
        <a v-bind:href="fav_3" target="_blank" > <img v-if="fav_3" v-bind:src="fav_3" class="pic2"/> </a>
        <a v-bind:href="fav_4" target="_blank" > <img v-if="fav_4" v-bind:src="fav_4" class="pic2"/> </a> 
        <a v-bind:href="fav_5" target="_blank" > <img v-if="fav_5" v-bind:src="fav_5" class="pic2"/> </a>
        <a v-bind:href="fav_6" target="_blank"> <img v-if="fav_6" v-bind:src="fav_6" class="pic2"/>  </a>
        <a v-bind:href="fav_7" target="_blank"> <img v-if="fav_7" v-bind:src="fav_7" class="pic2"/> </a>
        <a v-bind:href="fav_8" target="_blank" > <img v-if="fav_8" v-bind:src="fav_8" class="pic2"/> </a>
        <a v-bind:href="fav_9" target="_blank" > <img v-if="fav_9" v-bind:src="fav_9" class="pic2"/> </a> 
        <a v-bind:href="fav_10" target="_blank" > <img v-if="fav_10" v-bind:src="fav_10" class="pic2"/> </a>

    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>


    <script>
        var favlist =[];
        var u0,u1,u2,u3,u4,u5,u6;

        var strage = [];
        var s = localStorage.getItem('imgs');

        /// お気に入りようの配列///
        if(localStorage.getItem('fav')){
            // JSON.parse(data) の形で取り出す必要がある。
            // ocalStorage.getItem('imgs').lengthにすると文字の長さになってしまうからダメ。JSON.parse()する
            for(let i = 0 ; i < JSON.parse(localStorage.getItem('fav')).length -1 ; i++){
                favlist.push(JSON.parse(localStorage.getItem('fav'))[i]);
              }
         }       

        /// 過去画像ようの配列////
         if(localStorage.getItem('imgs')){
            // JSON.parse(data) の形で取り出す必要がある。
            // ocalStorage.getItem('imgs').lengthにすると文字の長さになってしまうからダメ。JSON.parse()する
            for(let k = 0 ; k < JSON.parse(localStorage.getItem('imgs')).length -1 ; k++){
                 strage.push(JSON.parse(localStorage.getItem('imgs'))[k]);
              }
         }

        ////////// メイン処理 //////////
        const app = new Vue({
            el: '#app',
            data: {
                src:''  , 
                his_1: '',
                his_2: '',
                his_3: '',
                his_4: '',
                his_5: '',
                good: false,
                fav_1: '',
                fav_2: '',
                fav_3: '',
                fav_4: '',
                fav_5: '',
                fav_6: '',
                fav_7: '',
                fav_8: '',
                fav_9: '',
                fav_10: ''

            },

            /// 過去の履歴を出すところ
            methods: {
                getData: async function(){
                    const URL = 'https://dog.ceo/api/breeds/image/random';
                    const response = await axios.get(URL);

                    this.message = response.data;
                    this.src = response.data.message;

                    // local strageにため込む処理
                    strage.unshift({url:this.src}); //先頭に追加
                    // 5こ以上は消す
                    strage = strage.slice(0,6);
                    localStorage.removeItem('imgs'); //imgsだけ消す
                    localStorage.setItem('imgs',JSON.stringify(strage)); // JSON.stringify(data) の形が需要。
                    console.log(strage);
                    u0 = this.src;

                    // 過去見たものの表示をする
                    if(localStorage.getItem('imgs')){
                        // エラーを防ぐ為に、過去履歴が存在するときだけ、その分だけ表示する
                        for(let j = 0 ; j < JSON.parse(localStorage.getItem('imgs')).length ; j++){
                            eval("this.his_"+ j + "= JSON.parse(localStorage.getItem('imgs'))[" + j + "].url");
                            // 普通に this.his_j = JSON.parse(localStorage.getItem('imgs'))[j].url;とは書けない
                        }
                    }

                    console.log(this.his_1);
                    this.good = false; // 画像が変わったらボタンを変える

                },

                ///お気に入り登録する機能
                favo: function(){

                    this.url = u0;
                    favlist.unshift({url:this.url});

                    localStorage.setItem('fav',JSON.stringify(favlist));
                    this.good = true ;

                    console.log(favlist);
                    console.log(this.good);

                    ///表示する
                   if(localStorage.getItem('fav')){
                       // 存在確認とあまりにお気に入りが多い場合は10個にする
                       var len1 = JSON.parse(localStorage.getItem('fav')).length;
                       if(len1 > 10){
                           len1 = 10;
                       }

                        // エラーを防ぐ為に、過去履歴が存在するときだけ、その分だけ表示する
                        for(let a = 0 ; a < len1 ; a++){
                            eval("this.fav_"+ (a+1) + "= JSON.parse(localStorage.getItem('fav'))[" + a + "].url");
                            // a番目のものをfav_a+1に格納する
                            // 普通に this.his_j = JSON.parse(localStorage.getItem('imgs'))[j].url;とは書けない
                        }
                    }                  

                },

                /// お気に入りから削除する機能
                delfavo: function(){
                    favlist.shift();
                    //JSON.parse(localStorage.getItem('fav')).shift();
                    localStorage.setItem('fav',JSON.stringify(favlist));
                    this.good = false ; // falseに戻す
                    console.log(favlist);

                    if(localStorage.getItem('fav')){
                    // 存在確認とあまりにお気に入りが多い場合は10個にする
                       var len2 = JSON.parse(localStorage.getItem('fav')).length;
                       if(len2 > 10){
                           len2 = 10;
                       }

                        // エラーを防ぐ為に、過去履歴が存在するときだけ、その分だけ表示する
                        for(let b = 0 ; b < len2 ; b++){
                            eval("this.fav_"+ (b+1) + "= JSON.parse(localStorage.getItem('fav'))[" + b + "].url");
                            // b番目のものをfav_b+1に格納する
                            // 普通に this.his_j = JSON.parse(localStorage.getItem('imgs'))[j].url;とは書けない
                        }
                    } 
                }

            },

            mounted: function(){
                this.getData();
                this.favo();
                this.delfavo();
            }
        })

    </script>

  </body>
</html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Angularの公式ドキュメントをざっくり読む(はじめてのアプリ~ルーティング)

こんばんは。社会人になりましてフロントエンド周りの勉強を始めまして、
まずAngularというフレームワークを勉強し始めました。
手始めに公式ドキュメントの「入門」の「はじめてのアプリ」から「ルーティング」までを読んでみて、理解したことなどをメモってみました。

Angularの公式サイト

中の人について

  • エンジニアで採用され、まずはフロントエンドの担当に
  • 昔pythonは書いていたが、スキル is 低い
  • まずはここからということで公式docを読んでる ←イマココ!

という訳で、Qiitaヤクザ造形の深い皆様は、
「まったく分かってないやん・・・」とキレずにコメントなどで
お手柔らかにご教授くださいませ(わがまま)

Angularってなに?

調べた内容をまとめてみました。

  • フレームワーク
  • 画面まわりを作成する際に便利
  • HTML, CSS, JavaScriptの見た目に関する機能に加えてページ移動に関すること(ルーティング)などの機能もある  ↑比較ででてくるVueとかReactとかは後者がない模様。
  • JavaScriptの上位互換であるTypeScriptが使用されている  ↑型の宣言ができる点で上位互換とのこと

といった感じで、すごい便利そう(小並感)
では、実際に読んで分かったことなどをまとめていきます。

はじめてのアプリ

基礎が書かれています。が基礎だけにめちゃ大切なことが書かれてます。

分かったこと

  • 「プロパティ」・・・ざっくりと変数のこと
  • 「属性」・・・ざっくりと数値や文字列のこと。
  • 「バインド」・・・プロパティに数値・文字列をいれるようなもの (紐づけてバインドするっていう連想が分かりやすそう)
  • インプットアウトプットの概念
    中々理解しづらい感じですが、以下リンクのボタン呼び出し側(親要素)に対して色・形(子要素)を渡す、という例がとてもいい感じ!
    Angularの@Input(), @Output()を理解する。
    ☆インプット:親→子へ属性を渡す & []を使用
    ☆アウトプット:子から親へ考え(ロジック)を渡す & ()を使用

    といった感じ・・・?

ルーティング

そもそもルーティングとは複数のページがあるときに、このページにはこのルートで行けば辿りつくよ、という道しるべの情報のこと(ざっくり)

ここからは、実際にコードを書く際にどんな流れなのかを書いてみました。
①コンポーネントを作成
「コンポーネント」・・・tsファイル, htmlファイル, cssファイル, scssファイルをまとめたもの。

②tsファイル内にpathとコンポーネント名のペアをつくる

こんな感じです。

src/app/app.module.ts(公式ドキュメントより引用)
RouterModule.forRoot([
{ path: '', component: ProductListComponent },
{ path: 'products/:productId', component: ProductDetailsComponent },
])

③htmlファイルにリンク先の設定をします。

src/app/product-list/product-list.component.html(公式ドキュメントより引用)
    <a [title]="product.name + ' details'"
       [routerLink]="['/products', productId]">
      {{ product.name }}
    </a>

ここで、②のpathと、③の[routerLink]の内容が同じになるように設定するようです。
これでルーティングの登録が完了しました。
以後はルーティング情報を使う流れになります。

④tsファイルでimportによって各種道具類をもってきます。

src/app/product-details/product-details.component.ts(公式ドキュメントより引用)
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { products } from '../products';

importで使えそうなイメージがありますが、以下の⑤を実行しないと使えない?ようです。
イメージとしては、
キャンプ場で金網やトングを借りてきました!(だけど持ってきただけで洗ってないので使えない・・・)みたいな感じかなと思います。

⑤tsファイルでexportによってクラス名を定義する

ここでウラス名を定義しますが、②のコンポーネント名と同じな点が重要。

src/app/product-details/product-details.component.ts(公式ドキュメントより引用)
//⑤の部分
export class ProductDetailsComponent implements OnInit {
  product;

  //⑥の部分
  constructor(
    private route: ActivatedRoute,
  ) { }

}

⑥tsファイルでコンストラクタで初期化して使えるようにする

上記コードのconstructorからの部分です。
これによって④で持ってきた道具類を初期化している、とのこと。
キャンプのたとえの場合、金網やトングを洗うことによって使用が可能になるイメージですね。

まとめ&今後の目標

そんなこんなで、初学者がドキュメントを読んで書いてみました。
公式ドキュメントが丁寧で分かりやすい(概念は少し難しいけど)のでこのまま続けていこうと思います。
今後はデータがどういう流れになっているのか?を図示したいところです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む