Vagrantのwebサーバに、ホストOSからJSONPでデータを受け取るという動作を試してみた
JSONPを参考にした本は以下です。(JSONPの説明は数ページだけです。)
※ただ試したというだけなので、あてにしないでください
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <p>JSONPテスト</p> <script> fetch('http://192.168.33.10/') .then(res=>console.log('ok')) .catch(err=>console.log('err')); </script> </body> </html>
想定どおりエラーがでた。
<?php switch($_GET['user'] ?? 0){ case 1: $json = json_encode([ 'name'=>'田中', 'age'=>20, ]); break; case 2: $json = json_encode([ 'name'=>'佐藤', 'age'=>25, ]); break; default: $json = json_encode([ 'name'=>'なし', 'age'=>0, ]); break; } header("Content-type: application/x-javascript; charset=utf-8"); echo ($_GET['callback'] ?? 'func')."(${json})";
- htmlを作成(ホストOSで実行)
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <p>JSONPテスト:<span></span></p> <input type="button" value="取得"> <script> 'use strict' document.addEventListener('DOMContentLoaded',function(){ document.querySelector('[type=button]').addEventListener('click',function(){ let sc = document.createElement("script"); sc.src = "http://192.168.33.10/test.php?user=1&callback=myfunc"; document.body.appendChild(sc); },false) },false) function myfunc(json){ document.querySelector('span').innerText = `${json.name}さんは${json.age}才`; } </script> </body> </html>
おー、できたできた!
ブラウザだけで、React.js+ES6+JSX動かせるのか、知らなかった
参考サイトのままです。 ちょっと試してみようって時とか便利そう。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <!-- Skipping all HTML5 boilerplate --> <script src="https://unpkg.com/react@16.2.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.2.0/umd/react-dom.development.js"></script> <!-- For JSX support (with babel) --> <script src="https://unpkg.com/babel-standalone@6.24.2/babel.min.js" charset="utf-8"></script> <div id="app"></div> <!-- React mounting point--> <script type="text/babel"> class Watch extends React.Component { render() { return <div>{this.props.hours}:{this.props.minutes}</div>; } } ReactDOM.render(<Watch hours="9" minutes="15"/>, document.getElementById('app')); </script> </body> </html>
phpのビルトインウェブサーバーからnode.jsのサーバにfetchでリクエスト
注意:これは自分が暇な時間にただだらだらと書いたコードを乗せるだけの投稿です。 技術的に勉強した部分や参考になる部分はありません。
- index.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> </style> </head> <body> <script> fetch('http://127.0.0.1:3000') .then(res=>res.json()) .then(json=>console.log(json)) </script> </body> </html>
- index.js
const http=require('http') const server=http.createServer() server.on('request',(req,res)=>{ res.writeHead(200,{ 'Access-Control-Allow-Origin':'*', 'Access-Control-Allow-Headers':'*', 'Content-Type':'application/json', }) res.write(JSON.stringify([1,2,3,4,5])) res.end() }) server.listen(3000,'127.0.0.1') console.log('server listenin...')
- ビルトインウェブサーバ起動
$ php -S 127.0.0.1:8000
- node.jsのサーバ起動
$ node index.js
chrome拡張で自分だけのリンク集を作成してみた
注意:この投稿はGWが暇だったため、なんとなく作ってみたものです。 ほとんど調べたりしていません。 ウンコードな部分も多いと思いますが、せっかく作ったのでブログに投稿しようと思っただけです。
chrome拡張の右上の小窓で、こんな感じのリンク集とリンク先の最終更新日が開いてくれたら、すごく自分には便利だったため、作りました。
作成方法
$ git clone git@github.com:okumurakengo/reactvuelink.git $ cd reactvuelink
chrome://extensions/
パッケージ化されていない拡張機能を読み込む
↓
cloneしてきたフォルダを指定
↓
chromeの右上にアイコンができる
最終更新日をパソコン起動時にスクレイピングで取得
- スクレイピング用にパッケージをインストール
$ npm i
- macからscraping.jsを自動実行する
Automatorを起動し、「アプリケーション」を選択
↓
「シェルスクリプトを実行」をダブルクリックすると、シェルを書くエディターが出てくる
以下のように設定し、保存する。
cd /Users/<cloneしたディレクトリ>/reactvuelink /Users/<nodeをインストールしたディレクトリ>/node scraping.js
↓
「システム環境設定」>「ユーザーとグループ」 「ログイン項目」を選び、今保存したシェルを実行するだけのアプリを登録しておく
パソコンを再起動するか、Automatorで作成したアプリをダブルクリックするたびに、 リンク先の最終更新日時を取得したlink_update.jsonができる。
link_update.jsonをpopup.htmlで読み込んでリンク集に最終更新日、最新投稿タイトルをつけてくれる
- 工夫してみた点
たくさんリンクがあったほうが自分も便利なので、リンク先を増やしたい時にやりやすくは考えてみた
- link.jsonの中にリンク先を増やす
[ { "no":101, "type":"vue", "name":"Vue.js News", "url":"https://news.vuejs.org/", "rss":"https://vuenews.fireside.fm/rss" }, { "no":102, "type":"react", "name":"reactjs.org", "url":"https://reactjs.org/blog/" }, + { + "no":103, + "type":"react", + "name":"Hatena::Bookmark react", + "url":"http://b.hatena.ne.jp/search/text?safe=on&q=react&users=3" + } ]
- scraping.jsで取得したいタグを指定
const fs = require('fs') ,client = require('cheerio-httpcli'); let link_update = JSON.parse(fs.readFileSync('./link.json','utf8')) ,link_option = [] ,url,title,date; Promise.resolve().then(()=>{ return new Promise((resolve, reject)=>{ (function loop(i=0){ // rssがある場合はrssを取得 url=link_update[i].rss ? link_update[i].rss : link_update[i].url; client.fetch(url,{},(err,$,res)=>{ if(err) { console.log(err); return; } switch(link_update[i].no){ case 102: // reactjs.org title = $('h1').text().trim(); date = $('h1').parent().next().text().replace(/by.*$/,''); break; + case 103: + // Hatena::Bookmark + title = $('.search-result:nth-of-type(1) h3').text().trim(); + date = $('.search-result:nth-of-type(1) .created').text(); + naiyou = $('.search-result:nth-of-type(1) blockquote').text(); + break; default: // rss title = $('item:nth-of-type(1)').find('title').text(); date = $('item:nth-of-type(1)').find('pubDate').text(); break; } link_option.push({title,date}); if(link_update[i+1]){ loop(i+1); return; } resolve(); }); })(); }); }).then(()=>{ link_update = link_update.map((obj,index)=>{ obj.title=link_option[index].title; obj.date=link_option[index].date; return obj; }); fs.writeFile('./link_update.json',JSON.stringify(link_update,undefined,1),err=>{ if (err) { console.log(err); return; } }); });
はてなブックマークの「react」で検索した一番上の情報が取れた!
vuejs.orgをただ読んでいくだけ - その2
このURLをただ読んでいきます。 https://jp.vuejs.org/v2/guide/
- Vue.js v2.5.16
はじめに
開発用と本番用で分けてくれるってありがたい、その分ファイル軽くなるものねえ。
<!-- 開発バージョン、便利なコンソールの警告が含まれています --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 本番バージョン、サイズと速度のために最適化されています --> <script src="https://cdn.jsdelivr.net/npm/vue"></script>
宣言的レンダリング
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>vue</title> </head> <body> <div id="app"> {{ message }} </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } }) </script> </body> </html>
最近、dataというオブジェクト内の変数がhtmlと連動するというすごくわかりやすい説明を見かけた!
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>vue</title> </head> <body> <div id="app-2"> <span v-bind:title="message"> Hover your mouse over me for a few seconds to see my dynamically bound title! </span> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#app-2', data: { message: 'You loaded this page on ' + new Date().toLocaleString() } }) </script> </body> </html>
title属性ってマウス当てないと出てこないからちょっとわかりずらいよね
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>vue</title> </head> <body> <div id="app-3"> <span v-if="seen">Now you see me</span> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#app-3', data: { seen: true } }) </script> </body> </html>
これで表示されるかどうかってことか。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>vue</title> </head> <body> <div id="app-4"> <ol> <li v-for="todo in todos"> {{ todo.text }} </li> </ol> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app4 = new Vue({ el: '#app-4', data: { todos: [ { text: 'Learn JavaScript' }, { text: 'Learn Vue' }, { text: 'Build something awesome' } ] } }) </script> </body> </html>
やっぱり配列をループ処理できるとデータベースの値とかも処理しやすいからね
ユーザー入力の制御
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>vue</title> </head> <body> <div id="app-5"> <p>{{ message }}</p> <button v-on:click="reverseMessage">Reverse Message</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app5 = new Vue({ el: '#app-5', data: { message: 'Hello Vue.js!' }, methods: { reverseMessage: function () { this.message = this.message.split('').reverse().join('') } } }) </script> </body> </html>
vue.jsというより、文字を反転させる方法がすごい勉強になる
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>vue</title> </head> <body> <div id="app-6"> <p>{{ message }}</p> <input v-model="message"> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app6 = new Vue({ el: '#app-6', data: { message: 'Hello Vue!' } }) </script> </body> </html>
入力してすぐ変わっていくってしょっちゅう使うよなあ
コンポーネントによる構成
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>vue</title> </head> <body> <div id="app-7"> <ol> <!-- 各 todo-item の内容を表す todo オブジェクトを与えます。 これにより内容は動的に変化します。 また後述する "key" を各コンポーネントに提供する必要があります。 --> <todo-item v-for="item in groceryList" v-bind:todo="item"></todo-item> </ol> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) var app7 = new Vue({ el: '#app-7', data: { groceryList: [ { id: 0, text: 'Vegetables' }, { id: 1, text: 'Cheese' }, { id: 2, text: 'Whatever else humans are supposed to eat' } ] } }) </script> </body> </html>
コンポーネントは使えないと話にならないんだろうなあ
vuejs.orgをただ読んでいくだけ - その1
スコープ付き CSS · vue-loader トップページの「なぜ VUE.JS」をクリックしたら動画が始まったため、とりあえず、見よう見まねで似たようなコードを書いてみました。
index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js</title> </head> <body> <div id="app"> <component-c></component-c> </div> <script src="https://unpkg.com/vue@2.5.16/dist/vue.min.js"></script> <script src="https://unpkg.com/http-vue-loader@1.3.4/src/httpVueLoader.js"></script> <script> document.addEventListener('DOMContentLoaded', function() { new Vue({ el: '#app', components: { 'component-c': httpVueLoader('./c.vue'), }, }); }); </script> </body> </html>
c.vue
<template> <ul> <li v-for="(product,index) in products" :key="index"> {{ product }} </li> </ul> </template> <script> module.exports = { data: () => { return { products:[ 'Boots', 'Jackets', 'Hiking Socks' ] } }, created:()=>{ console.log(new Date); } } </script> <style scoped> li { color: royalblue; } </style>
とりあえず、vue.js使って画面表示までできた
Server-Sent Eventsを試してみた
参考にしたサイトとほぼ同じコードですが、SSEで実行することができました!
Server-Sent Events の利用 - Server-sent events | MDN
- index.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <ul id="list"></ul> <script> var evtSource = new EventSource("ssedemo.php"); evtSource.addEventListener("ping", function(e) { var newElement = document.createElement("li"); var eventList = document.getElementById('list'); console.log(e.data); var obj = JSON.parse(e.data); newElement.innerHTML = "ping at " + obj.time; eventList.appendChild(newElement); }, false); evtSource.addEventListener("error",function(e){ console.log(e); alert("EventSource failed."); },false); </script> </body> </html>
- ssedemo.php
<?php date_default_timezone_set("America/New_York"); header("Content-Type: text/event-stream\n\n"); $counter = rand(1, 10); while (1) { // "ping" イベントを毎秒送信 echo "event: ping\n"; echo 'data: {"time": "' . (new DateTime())->format('Y/m/d H:i:s') . '"}'; echo "\n\n"; // シンプルなメッセージをランダムな間隔で送信 $counter--; if (!$counter) { echo "event: ping2\n"; echo 'data: This is a message at time ' . (new DateTime())->format('Y/m/d') . "\n\n"; $counter = rand(1, 10); } if (ob_get_contents()) ob_end_clean(); flush(); sleep(1); }
すごい!!