92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线

首頁

git入門:Linux操作系統下 git環境搭建 | 生成公私密鑰

前端達人

前言

該示例是在ubuntu下完成的

 

 

一、安裝 git 和 ssh

sudo apt-get install git
sudo apt-get install openssh-server

二、配置公鑰

因為git和 GitHub之間是通過ssh加密傳輸的,因此需要配置公鑰,所以需要先生成公私密鑰。

命令:該郵箱是你注冊GitHub的郵箱地址

ssh-keygen -t rsa -C “xxxxxxxxxx@163.com”

如圖,表示生成成功

三、得到公鑰在GitHub配置

進入 .ssh 文件里,查看id_rsa.pub,表示公鑰(public)

復制該密鑰到GitHub里配置

標題title隨便起

四、查看能否通信成功

輸入該命令:如果出現下面這句話,就說明成功了。

ssh -T git@github.com

五、配置郵箱和用戶名

通過以下兩個命令配置用戶名和郵箱,以后提交代碼文件,就會附帶該用戶的信息。

git config --global user.name " xxx "
git config --global user.email " xxx@xx.com"

在 .gitconfig文件可查看

藍藍設計(m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的大數據可視化界面設計、B端界面設計、桌面端界面設計、APP界面設計、圖標定制、用戶體驗設計、交互設計、UI咨詢、高端網站設計平面設計,以及相關的軟件開發服務,咨詢電話:01063334945。

關鍵詞:UI咨詢、UI設計服務公司、軟件界面設計公司、界面設計公司、UI設計公司、UI交互設計公司、數據可視化設計公司、用戶體驗公司高端網站設計公司

銀行金融軟件UI界面設計、能源及監控軟件UI界面設計氣象行業UI界面設計、軌道交通界面設計、地理信息系統GIS UI界面設計航天軍工軟件UI界面設計、醫療行業軟件UI界面設計教育行業軟件UI界面設計、企業信息化UI界面設計、軟件qt開發、軟件wpf開發、軟件vue開發

4個步驟,總結B端設計師的競品分析方法|北京藍藍UI設計公司

高勁

競品分析方法很多,但大多數是偏向 B 端產品經理方面的或者是 C 端設計師的,真正在 B 端設計中的方法比較少,這次為大家介紹適合 B 端設計師使用的競品分析方法。

如何拆解UI界面設計?試試這個三維分析法?。本┧{藍UI設計公司

高勁

界面設計就是將一堆分散的元素、內容或者組件,通過正確使用可視層次結構,進行合理的規劃和重組,有目的地呈現在用戶的面前,這樣有助于內容傳達和提升用戶使用效率,幫助用戶快速解決問題。

10個產品細節剖析,看看高手是如何做設計的!|北京藍藍UI設計公司

高勁

俗話說:“細節決定成敗”,對于設計而言亦是如此,把設計做到極致才能在競爭中脫穎而出。對于產品設計師來說不僅需要有發現的眼睛,也要有做到極致的習慣。通過優秀的設計案例不斷培養自己的設計思維,才能在項目中不斷創新和做到極致。

最近黑馬哥發現了一些優秀的設計細節,相信這些小小的細節必然可以帶來更好的體驗,助力產品帶給用戶更好的使用體驗。

 

4000字干貨!幫你快速了解產品設計中的心智模式|北京藍藍UI設計公司

高勁

進入主題之前,向大家強烈推薦李睿秋先生的《打開心智》一書,雖然書名有一點成功學,但是內容非常有參考性。本次分享內容的核心也來源于《打開心智》一書,自己僅做了內容的整理與 PPT 設計。

好看的圣誕樹(動態效果) 轉自 csdn

前端達人

、制作方法 

1.復制代碼到Dreamweaver或HBuilder或vscode中

2.點擊運行---運行到瀏覽器---選擇你要打開的瀏覽器

3.打開后會出現這個界面,前四個是固定音樂,最后一個是自主選擇的音樂,你可以選擇你電腦上的歌曲,什么歌曲都行(第一次打開可能會有點慢,稍等片刻即可,選擇音樂的時候點一下沒反應的話多點幾下即可,第一次打開這屬于正?,F象)

 

4.特別提醒:打開的時候電腦一定要處于聯網狀態
 

三、源代碼

 
  1.  
    <!DOCTYPE html>
  2.  
    <html lang="en">
  3.  
     
  4.  
    <head>
  5.  
    <meta charset="UTF-8">
  6.  
     
  7.  
    <title>圣誕樹</title>
  8.  
     
  9.  
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
  10.  
     
  11.  
    <style>
  12.  
    * {
  13.  
    box-sizing: border-box;
  14.  
    }
  15.  
     
  16.  
     
  17.  
    body {
  18.  
    margin: 0;
  19.  
    height: 100vh;
  20.  
    overflow: hidden;
  21.  
    display: flex;
  22.  
    align-items: center;
  23.  
    justify-content: center;
  24.  
    background: #161616;
  25.  
    color: #c5a880;
  26.  
    font-family: sans-serif;
  27.  
    }
  28.  
     
  29.  
     
  30.  
    label {
  31.  
    display: inline-block;
  32.  
    background-color: #161616;
  33.  
    padding: 16px;
  34.  
    border-radius: 0.3rem;
  35.  
    cursor: pointer;
  36.  
    margin-top: 1rem;
  37.  
    width: 300px;
  38.  
    border-radius: 10px;
  39.  
    border: 1px solid #c5a880;
  40.  
    text-align: center;
  41.  
    }
  42.  
     
  43.  
     
  44.  
    ul {
  45.  
    list-style-type: none;
  46.  
    padding: 0;
  47.  
    margin: 0;
  48.  
    }
  49.  
     
  50.  
     
  51.  
    .btn {
  52.  
    background-color: #161616;
  53.  
    border-radius: 10px;
  54.  
    color: #c5a880;
  55.  
    border: 1px solid #c5a880;
  56.  
    padding: 16px;
  57.  
    width: 300px;
  58.  
    margin-bottom: 16px;
  59.  
    line-height: 1.5;
  60.  
    cursor: pointer;
  61.  
    }
  62.  
     
  63.  
    .separator {
  64.  
    font-weight: bold;
  65.  
    text-align: center;
  66.  
    width: 300px;
  67.  
    margin: 16px 0px;
  68.  
    color: #a07676;
  69.  
    }
  70.  
     
  71.  
     
  72.  
    .title {
  73.  
    color: #a07676;
  74.  
    font-weight: bold;
  75.  
    font-size: 1.25rem;
  76.  
    margin-bottom: 16px;
  77.  
    }
  78.  
     
  79.  
     
  80.  
    .text-loading {
  81.  
    font-size: 2rem;
  82.  
    }
  83.  
    </style>
  84.  
     
  85.  
    <script>
  86.  
    window.console = window.console || function (t) { };
  87.  
    </script>
  88.  
     
  89.  
     
  90.  
     
  91.  
    <script>
  92.  
    if (document.location.search.match(/type=embed/gi)) {
  93.  
    window.parent.postMessage("resize", "*");
  94.  
    }
  95.  
    </script>
  96.  
     
  97.  
     
  98.  
    </head>
  99.  
     
  100.  
    <body translate="no">
  101.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/build/three.min.js"></script>
  102.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/EffectComposer.js"></script>
  103.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/RenderPass.js"></script>
  104.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/ShaderPass.js"></script>
  105.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/CopyShader.js"></script>
  106.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/LuminosityHighPassShader.js"></script>
  107.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/UnrealBloomPass.js"></script>
  108.  
     
  109.  
    <div id="overlay">
  110.  
    <ul>
  111.  
    <li class="title">請選擇音樂</li>
  112.  
    <li>
  113.  
    <button class="btn" id="btnA" type="button">
  114.  
    Snowflakes Falling Down by Simon Panrucker
  115.  
    </button>
  116.  
    </li>
  117.  
    <li><button class="btn" id="btnB" type="button">This Christmas by Dott</button></li>
  118.  
    <li><button class="btn" id="btnC" type="button">No room at the inn by TRG Banks</button></li>
  119.  
    <li><button class="btn" id="btnD" type="button">Jingle Bell Swing by Mark Smeby</button></li>
  120.  
    <li class="separator">或者</li>
  121.  
    <li>
  122.  
    <input type="file" id="upload" hidden />
  123.  
    <label for="upload">Upload File</label>
  124.  
    </li>
  125.  
    </ul>
  126.  
    </div>
  127.  
     
  128.  
    <script id="rendered-js">
  129.  
    const { PI, sin, cos } = Math;
  130.  
    const TAU = 2 * PI;
  131.  
     
  132.  
    const map = (value, sMin, sMax, dMin, dMax) => {
  133.  
    return dMin + (value - sMin) / (sMax - sMin) * (dMax - dMin);
  134.  
    };
  135.  
     
  136.  
    const range = (n, m = 0) =>
  137.  
    Array(n).
  138.  
    fill(m).
  139.  
    map((i, j) => i + j);
  140.  
     
  141.  
    const rand = (max, min = 0) => min + Math.random() * (max - min);
  142.  
    const randInt = (max, min = 0) => Math.floor(min + Math.random() * (max - min));
  143.  
    const randChoise = arr => arr[randInt(arr.length)];
  144.  
    const polar = (ang, r = 1) => [r * cos(ang), r * sin(ang)];
  145.  
     
  146.  
    let scene, camera, renderer, analyser;
  147.  
    let step = 0;
  148.  
    const uniforms = {
  149.  
    time: { type: "f", value: 0.0 },
  150.  
    step: { type: "f", value: 0.0 }
  151.  
    };
  152.  
     
  153.  
    const params = {
  154.  
    exposure: 1,
  155.  
    bloomStrength: 0.9,
  156.  
    bloomThreshold: 0,
  157.  
    bloomRadius: 0.5
  158.  
    };
  159.  
     
  160.  
    let composer;
  161.  
     
  162.  
    const fftSize = 2048;
  163.  
    const totalPoints = 4000;
  164.  
     
  165.  
    const listener = new THREE.AudioListener();
  166.  
     
  167.  
    const audio = new THREE.Audio(listener);
  168.  
     
  169.  
    document.querySelector("input").addEventListener("change", uploadAudio, false);
  170.  
     
  171.  
    const buttons = document.querySelectorAll(".btn");
  172.  
    buttons.forEach((button, index) =>
  173.  
    button.addEventListener("click", () => loadAudio(index)));
  174.  
     
  175.  
     
  176.  
    function init() {
  177.  
    const overlay = document.getElementById("overlay");
  178.  
    overlay.remove();
  179.  
     
  180.  
    scene = new THREE.Scene();
  181.  
    renderer = new THREE.WebGLRenderer({ antialias: true });
  182.  
    renderer.setPixelRatio(window.devicePixelRatio);
  183.  
    renderer.setSize(window.innerWidth, window.innerHeight);
  184.  
    document.body.appendChild(renderer.domElement);
  185.  
     
  186.  
    camera = new THREE.PerspectiveCamera(
  187.  
    60,
  188.  
    window.innerWidth / window.innerHeight,
  189.  
    1,
  190.  
    1000);
  191.  
     
  192.  
    camera.position.set(-0.09397456774197047, -2.5597086635726947, 24.420789670889008);
  193.  
    camera.rotation.set(0.10443543723052419, -0.003827152981119352, 0.0004011488708739715);
  194.  
     
  195.  
    const format = renderer.capabilities.isWebGL2 ?
  196.  
    THREE.RedFormat :
  197.  
    THREE.LuminanceFormat;
  198.  
     
  199.  
    uniforms.tAudioData = {
  200.  
    value: new THREE.DataTexture(analyser.data, fftSize / 2, 1, format)
  201.  
    };
  202.  
     
  203.  
     
  204.  
    addPlane(scene, uniforms, 3000);
  205.  
    addSnow(scene, uniforms);
  206.  
     
  207.  
    range(10).map(i => {
  208.  
    addTree(scene, uniforms, totalPoints, [20, 0, -20 * i]);
  209.  
    addTree(scene, uniforms, totalPoints, [-20, 0, -20 * i]);
  210.  
    });
  211.  
     
  212.  
    const renderScene = new THREE.RenderPass(scene, camera);
  213.  
     
  214.  
    const bloomPass = new THREE.UnrealBloomPass(
  215.  
    new THREE.Vector2(window.innerWidth, window.innerHeight),
  216.  
    1.5,
  217.  
    0.4,
  218.  
    0.85);
  219.  
     
  220.  
    bloomPass.threshold = params.bloomThreshold;
  221.  
    bloomPass.strength = params.bloomStrength;
  222.  
    bloomPass.radius = params.bloomRadius;
  223.  
     
  224.  
    composer = new THREE.EffectComposer(renderer);
  225.  
    composer.addPass(renderScene);
  226.  
    composer.addPass(bloomPass);
  227.  
     
  228.  
    addListners(camera, renderer, composer);
  229.  
    animate();
  230.  
    }
  231.  
     
  232.  
    function animate(time) {
  233.  
    analyser.getFrequencyData();
  234.  
    uniforms.tAudioData.value.needsUpdate = true;
  235.  
    step = (step + 1) % 1000;
  236.  
    uniforms.time.value = time;
  237.  
    uniforms.step.value = step;
  238.  
    composer.render();
  239.  
    requestAnimationFrame(animate);
  240.  
    }
  241.  
     
  242.  
    function loadAudio(i) {
  243.  
    document.getElementById("overlay").innerHTML =
  244.  
    '<div class="text-loading">正在下載音樂,請稍等...</div>';
  245.  
    const files = [
  246.  
    "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Simon_Panrucker/Happy_Christmas_You_Guys/Simon_Panrucker_-_01_-_Snowflakes_Falling_Down.mp3",
  247.  
    "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Dott/This_Christmas/Dott_-_01_-_This_Christmas.mp3",
  248.  
    "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/ccCommunity/TRG_Banks/TRG_Banks_Christmas_Album/TRG_Banks_-_12_-_No_room_at_the_inn.mp3",
  249.  
    "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/ccCommunity/Mark_Smeby/En_attendant_Nol/Mark_Smeby_-_07_-_Jingle_Bell_Swing.mp3"];
  250.  
     
  251.  
    const file = files[i];
  252.  
     
  253.  
    const loader = new THREE.AudioLoader();
  254.  
    loader.load(file, function (buffer) {
  255.  
    audio.setBuffer(buffer);
  256.  
    audio.play();
  257.  
    analyser = new THREE.AudioAnalyser(audio, fftSize);
  258.  
    init();
  259.  
    });
  260.  
     
  261.  
     
  262.  
     
  263.  
     
  264.  
    }
  265.  
     
  266.  
     
  267.  
    function uploadAudio(event) {
  268.  
    document.getElementById("overlay").innerHTML =
  269.  
    '<div class="text-loading">請稍等...</div>';
  270.  
    const files = event.target.files;
  271.  
    const reader = new FileReader();
  272.  
     
  273.  
    reader.onload = function (file) {
  274.  
    var arrayBuffer = file.target.result;
  275.  
     
  276.  
    listener.context.decodeAudioData(arrayBuffer, function (audioBuffer) {
  277.  
    audio.setBuffer(audioBuffer);
  278.  
    audio.play();
  279.  
    analyser = new THREE.AudioAnalyser(audio, fftSize);
  280.  
    init();
  281.  
    });
  282.  
    };
  283.  
     
  284.  
    reader.readAsArrayBuffer(files[0]);
  285.  
    }
  286.  
     
  287.  
    function addTree(scene, uniforms, totalPoints, treePosition) {
  288.  
    const vertexShader = `
  289.  
    attribute float mIndex;
  290.  
    varying vec3 vColor;
  291.  
    varying float opacity;
  292.  
    uniform sampler2D tAudioData;
  293.  
    float norm(float value, float min, float max ){
  294.  
    return (value - min) / (max - min);
  295.  
    }
  296.  
    float lerp(float norm, float min, float max){
  297.  
    return (max - min) * norm + min;
  298.  
    }
  299.  
    float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
  300.  
    return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
  301.  
    }
  302.  
    void main() {
  303.  
    vColor = color;
  304.  
    vec3 p = position;
  305.  
    vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
  306.  
    float amplitude = texture2D( tAudioData, vec2( mIndex, 0.1 ) ).r;
  307.  
    float amplitudeClamped = clamp(amplitude-0.4,0.0, 0.6 );
  308.  
    float sizeMapped = map(amplitudeClamped, 0.0, 0.6, 1.0, 20.0);
  309.  
    opacity = map(mvPosition.z , -200.0, 15.0, 0.0, 1.0);
  310.  
    gl_PointSize = sizeMapped * ( 100.0 / -mvPosition.z );
  311.  
    gl_Position = projectionMatrix * mvPosition;
  312.  
    }
  313.  
    `;
  314.  
    const fragmentShader = `
  315.  
    varying vec3 vColor;
  316.  
    varying float opacity;
  317.  
    uniform sampler2D pointTexture;
  318.  
    void main() {
  319.  
    gl_FragColor = vec4( vColor, opacity );
  320.  
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
  321.  
    }
  322.  
    `;
  323.  
    const shaderMaterial = new THREE.ShaderMaterial({
  324.  
    uniforms: {
  325.  
    ...uniforms,
  326.  
    pointTexture: {
  327.  
    value: new THREE.TextureLoader().load(`https://assets.codepen.io/3685267/spark1.png`)
  328.  
    }
  329.  
    },
  330.  
     
  331.  
     
  332.  
    vertexShader,
  333.  
    fragmentShader,
  334.  
    blending: THREE.AdditiveBlending,
  335.  
    depthTest: false,
  336.  
    transparent: true,
  337.  
    vertexColors: true
  338.  
    });
  339.  
     
  340.  
     
  341.  
    const geometry = new THREE.BufferGeometry();
  342.  
    const positions = [];
  343.  
    const colors = [];
  344.  
    const sizes = [];
  345.  
    const phases = [];
  346.  
    const mIndexs = [];
  347.  
     
  348.  
    const color = new THREE.Color();
  349.  
     
  350.  
    for (let i = 0; i < totalPoints; i++) {
  351.  
    const t = Math.random();
  352.  
    const y = map(t, 0, 1, -8, 10);
  353.  
    const ang = map(t, 0, 1, 0, 6 * TAU) + TAU / 2 * (i % 2);
  354.  
    const [z, x] = polar(ang, map(t, 0, 1, 5, 0));
  355.  
     
  356.  
    const modifier = map(t, 0, 1, 1, 0);
  357.  
    positions.push(x + rand(-0.3 * modifier, 0.3 * modifier));
  358.  
    positions.push(y + rand(-0.3 * modifier, 0.3 * modifier));
  359.  
    positions.push(z + rand(-0.3 * modifier, 0.3 * modifier));
  360.  
     
  361.  
    color.setHSL(map(i, 0, totalPoints, 1.0, 0.0), 1.0, 0.5);
  362.  
     
  363.  
    colors.push(color.r, color.g, color.b);
  364.  
    phases.push(rand(1000));
  365.  
    sizes.push(1);
  366.  
    const mIndex = map(i, 0, totalPoints, 1.0, 0.0);
  367.  
    mIndexs.push(mIndex);
  368.  
    }
  369.  
     
  370.  
    geometry.setAttribute(
  371.  
    "position",
  372.  
    new THREE.Float32BufferAttribute(positions, 3).setUsage(
  373.  
    THREE.DynamicDrawUsage));
  374.  
     
  375.  
     
  376.  
    geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
  377.  
    geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
  378.  
    geometry.setAttribute("phase", new THREE.Float32BufferAttribute(phases, 1));
  379.  
    geometry.setAttribute("mIndex", new THREE.Float32BufferAttribute(mIndexs, 1));
  380.  
     
  381.  
    const tree = new THREE.Points(geometry, shaderMaterial);
  382.  
     
  383.  
    const [px, py, pz] = treePosition;
  384.  
     
  385.  
    tree.position.x = px;
  386.  
    tree.position.y = py;
  387.  
    tree.position.z = pz;
  388.  
     
  389.  
    scene.add(tree);
  390.  
    }
  391.  
     
  392.  
    function addSnow(scene, uniforms) {
  393.  
    const vertexShader = `
  394.  
    attribute float size;
  395.  
    attribute float phase;
  396.  
    attribute float phaseSecondary;
  397.  
    varying vec3 vColor;
  398.  
    varying float opacity;
  399.  
    uniform float time;
  400.  
    uniform float step;
  401.  
    float norm(float value, float min, float max ){
  402.  
    return (value - min) / (max - min);
  403.  
    }
  404.  
    float lerp(float norm, float min, float max){
  405.  
    return (max - min) * norm + min;
  406.  
    }
  407.  
    float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
  408.  
    return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
  409.  
    }
  410.  
    void main() {
  411.  
    float t = time* 0.0006;
  412.  
    vColor = color;
  413.  
    vec3 p = position;
  414.  
    p.y = map(mod(phase+step, 1000.0), 0.0, 1000.0, 25.0, -8.0);
  415.  
    p.x += sin(t+phase);
  416.  
    p.z += sin(t+phaseSecondary);
  417.  
    opacity = map(p.z, -150.0, 15.0, 0.0, 1.0);
  418.  
    vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
  419.  
    gl_PointSize = size * ( 100.0 / -mvPosition.z );
  420.  
    gl_Position = projectionMatrix * mvPosition;
  421.  
    }
  422.  
    `;
  423.  
     
  424.  
    const fragmentShader = `
  425.  
    uniform sampler2D pointTexture;
  426.  
    varying vec3 vColor;
  427.  
    varying float opacity;
  428.  
    void main() {
  429.  
    gl_FragColor = vec4( vColor, opacity );
  430.  
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
  431.  
    }
  432.  
    `;
  433.  
    function createSnowSet(sprite) {
  434.  
    const totalPoints = 300;
  435.  
    const shaderMaterial = new THREE.ShaderMaterial({
  436.  
    uniforms: {
  437.  
    ...uniforms,
  438.  
    pointTexture: {
  439.  
    value: new THREE.TextureLoader().load(sprite)
  440.  
    }
  441.  
    },
  442.  
     
  443.  
     
  444.  
    vertexShader,
  445.  
    fragmentShader,
  446.  
    blending: THREE.AdditiveBlending,
  447.  
    depthTest: false,
  448.  
    transparent: true,
  449.  
    vertexColors: true
  450.  
    });
  451.  
     
  452.  
     
  453.  
    const geometry = new THREE.BufferGeometry();
  454.  
    const positions = [];
  455.  
    const colors = [];
  456.  
    const sizes = [];
  457.  
    const phases = [];
  458.  
    const phaseSecondaries = [];
  459.  
     
  460.  
    const color = new THREE.Color();
  461.  
     
  462.  
    for (let i = 0; i < totalPoints; i++) {
  463.  
    const [x, y, z] = [rand(25, -25), 0, rand(15, -150)];
  464.  
    positions.push(x);
  465.  
    positions.push(y);
  466.  
    positions.push(z);
  467.  
     
  468.  
    color.set(randChoise(["#f1d4d4", "#f1f6f9", "#eeeeee", "#f1f1e8"]));
  469.  
     
  470.  
    colors.push(color.r, color.g, color.b);
  471.  
    phases.push(rand(1000));
  472.  
    phaseSecondaries.push(rand(1000));
  473.  
    sizes.push(rand(4, 2));
  474.  
    }
  475.  
     
  476.  
    geometry.setAttribute(
  477.  
    "position",
  478.  
    new THREE.Float32BufferAttribute(positions, 3));
  479.  
     
  480.  
    geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
  481.  
    geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
  482.  
    geometry.setAttribute("phase", new THREE.Float32BufferAttribute(phases, 1));
  483.  
    geometry.setAttribute(
  484.  
    "phaseSecondary",
  485.  
    new THREE.Float32BufferAttribute(phaseSecondaries, 1));
  486.  
     
  487.  
     
  488.  
    const mesh = new THREE.Points(geometry, shaderMaterial);
  489.  
     
  490.  
    scene.add(mesh);
  491.  
    }
  492.  
    const sprites = [
  493.  
    "https://assets.codepen.io/3685267/snowflake1.png",
  494.  
    "https://assets.codepen.io/3685267/snowflake2.png",
  495.  
    "https://assets.codepen.io/3685267/snowflake3.png",
  496.  
    "https://assets.codepen.io/3685267/snowflake4.png",
  497.  
    "https://assets.codepen.io/3685267/snowflake5.png"];
  498.  
     
  499.  
    sprites.forEach(sprite => {
  500.  
    createSnowSet(sprite);
  501.  
    });
  502.  
    }
  503.  
     
  504.  
    function addPlane(scene, uniforms, totalPoints) {
  505.  
    const vertexShader = `
  506.  
    attribute float size;
  507.  
    attribute vec3 customColor;
  508.  
    varying vec3 vColor;
  509.  
    void main() {
  510.  
    vColor = customColor;
  511.  
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
  512.  
    gl_PointSize = size * ( 300.0 / -mvPosition.z );
  513.  
    gl_Position = projectionMatrix * mvPosition;
  514.  
    }
  515.  
    `;
  516.  
    const fragmentShader = `
  517.  
    uniform vec3 color;
  518.  
    uniform sampler2D pointTexture;
  519.  
    varying vec3 vColor;
  520.  
    void main() {
  521.  
    gl_FragColor = vec4( vColor, 1.0 );
  522.  
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
  523.  
    }
  524.  
    `;
  525.  
    const shaderMaterial = new THREE.ShaderMaterial({
  526.  
    uniforms: {
  527.  
    ...uniforms,
  528.  
    pointTexture: {
  529.  
    value: new THREE.TextureLoader().load(`https://assets.codepen.io/3685267/spark1.png`)
  530.  
    }
  531.  
    },
  532.  
     
  533.  
     
  534.  
    vertexShader,
  535.  
    fragmentShader,
  536.  
    blending: THREE.AdditiveBlending,
  537.  
    depthTest: false,
  538.  
    transparent: true,
  539.  
    vertexColors: true
  540.  
    });
  541.  
     
  542.  
     
  543.  
    const geometry = new THREE.BufferGeometry();
  544.  
    const positions = [];
  545.  
    const colors = [];
  546.  
    const sizes = [];
  547.  
     
  548.  
    const color = new THREE.Color();
  549.  
     
  550.  
    for (let i = 0; i < totalPoints; i++) {
  551.  
    const [x, y, z] = [rand(-25, 25), 0, rand(-150, 15)];
  552.  
    positions.push(x);
  553.  
    positions.push(y);
  554.  
    positions.push(z);
  555.  
     
  556.  
    color.set(randChoise(["#93abd3", "#f2f4c0", "#9ddfd3"]));
  557.  
     
  558.  
    colors.push(color.r, color.g, color.b);
  559.  
    sizes.push(1);
  560.  
    }
  561.  
     
  562.  
    geometry.setAttribute(
  563.  
    "position",
  564.  
    new THREE.Float32BufferAttribute(positions, 3).setUsage(
  565.  
    THREE.DynamicDrawUsage));
  566.  
     
  567.  
     
  568.  
    geometry.setAttribute(
  569.  
    "customColor",
  570.  
    new THREE.Float32BufferAttribute(colors, 3));
  571.  
     
  572.  
    geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
  573.  
     
  574.  
    const plane = new THREE.Points(geometry, shaderMaterial);
  575.  
     
  576.  
    plane.position.y = -8;
  577.  
    scene.add(plane);
  578.  
    }
  579.  
     
  580.  
    function addListners(camera, renderer, composer) {
  581.  
    document.addEventListener("keydown", e => {
  582.  
    const { x, y, z } = camera.position;
  583.  
    console.log(`camera.position.set(${x},${y},${z})`);
  584.  
    const { x: a, y: b, z: c } = camera.rotation;
  585.  
    console.log(`camera.rotation.set(${a},$,${c})`);
  586.  
    });
  587.  
     
  588.  
    window.addEventListener(
  589.  
    "resize",
  590.  
    () => {
  591.  
    const width = window.innerWidth;
  592.  
    const height = window.innerHeight;
  593.  
     
  594.  
    camera.aspect = width / height;
  595.  
    camera.updateProjectionMatrix();
  596.  
     
  597.  
    renderer.setSize(width, height);
  598.  
    composer.setSize(width, height);
  599.  
    },
  600.  
    false);
  601.  
     
  602.  
    }
  603.  
    </script>
  604.  
     
  605.  
    </body>
  606.  
     
  607.  
    </html>
 

WebSocket:實現實時雙向數據傳輸的Web通信協議

前端達人

 

前言

在當今互聯網時代,實時通信已成為很多應用的需求。為了滿足這種需求,WebSocket協議被設計出來。WebSocket是一種基于TCP議的全雙工通信協議,通過WebSocket,Web應用程序可以與服務器建立持久的連接,實現實時雙向數據輸,提供極低的延遲和高效的數據傳輸。


WebSocket原理

  • HTTP請求-響應協議

在理解WebSocket原理之前,我們需要了解HTTP請求-響應協議。HTTP是一種無狀態的請求-響應協議,客戶端通過發送HTTP請求到服務器,服務器接收并處理請求,并返回HTTP響應給客戶端。但是,在傳統的HTTP協議中,客戶端只能發送請求,而服務器只能通過響應來處理客戶端的請求。

  • WebSocket協議

WebSocket協議是在HTTP協議的基礎上進行擴展的。在建立WebSocket連接時,客戶端首先發送一個HTTP請求到服務器,并將Upgrade頭部字段設置為"websocket",表示希望升級到WebSocket協議。服務器接收到這個請求后,如果支持WebSocket協議,會返回一個狀態碼101 Switching Protocols的HTTP響應,并通過Upgrade頭部字段將連接升級為WebSocket連接。

升級完成后,客戶端和服務器之間的通信不再遵循HTTP請求-響應模式,而是通過WebSocket協議進行雙向的實時通信??蛻舳撕头掌骺梢灾苯影l送消息給對方,不需要等待對方的請求。


如何使用WebSocket

建立WebSocket連接:

要建立WebSocket連接,需要在客戶端和服務器之間進行系列的握手操作。下面是詳細的代碼教程,示了如何在Web應用程序中建立WebSocket連接。

在戶端(JavaScript):

// 創建WebSocket對象并指定服務器地址
var socket = new WebSocket("ws://example.com/socket");

// 監聽連接建立事件
socket.onopen = function() {
console.log("WebSocket連接已建立");
// 在連接建立后,可以發送消息到服務器
socket.send("Hello Server!");
};


// 監聽接收到服務器發送的消息
socket.onmessage = function(event) {
var message = event.data;
console.log("接收到服務器發送的消息:" + message);
};


// 監聽連接關閉事件
socket.onclose = function(event) {
console.log("WebSocket連接已關閉");
};


// 監聽連接錯誤事件
socket.onerror = function(event) {
console.error("WebSocket連接錯誤:" + event};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在服務器端(示例使用Node.js):

const WebSocket = require("ws");

// 創建WebSocket服務器
const wss = new WebSocket.Server({ port: 8080 });


// 監聽連接建立事件
wss.on("connection", function(socket) {
console.log("WebSocket連接已建立");


// 監聽接收到客戶端發送的消息
socket.on("message", function(message) {
console.log("接收到戶端發送的消息:" + message);


<span class="token comment">// 向客戶端發送消息</span>
socket<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">"Hello Client!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

});


// 監聽連接關閉事件
socket.on("close", function() {
console.log("WebSocket連接已關閉");
});
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在以上代碼中,客戶端通過創建WebSocket對象,并指定服務器地址"ws://example.com/socket"來建立WebSocket連接。同時,客戶端通過監聽onopen事件,可以在連接建立后發送消息到服務器。服務器端使用WebSocket.Server類創建WebSocket服務器,并監聽"connection事件來處理連接建立后的操作。服務器端通過socket.on(“message”)來監聽接收到客戶端發送的消息,并通過socket.send()向客戶端發送消息。

數據傳輸:

建立WebSocket連接后,客戶端和服務器可以通過WebSocket對象進行雙向的實時數據傳輸。下面是一個示例代碼,演示了如何在客戶端和服務器之間進行數據傳輸。

在客戶端(JavaScript):

// 發送消息到服務器
socket.send("Hello Server!");

// 監聽接收到服務器發送的消息
socket.onmessage = function(event) {
var message = event.data;
console.log("接收到服務器發送的消息:" + message);
};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在服務器端(示例使用Node.js):

// 向客戶端發送消息
socket.send("Hello Client!");

// 監聽接收到客戶端發送的消息
socket.on("message", function(message) {
console.log("接收到客戶端發送的消息:" + message);
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在以上代碼中,客戶端通過調用socket.send()方法將消息發送到服務器,服務器通過socket.send()方法將消息發送到客戶端??蛻舳送ㄟ^監聽socket.onmessage事件來接收服務器發送的消息,服務器通過監聽socket.on("message")事件來接收客戶端發送的消息。

通過以上代碼示例,你可以詳細了解如何使用WebSocket建立連接并進行數據傳輸。請注意,示例代碼中使用的服務器地址和端口號需要根據實際情況進行修改。同時,你還可以在具體應用中根據需要使用WebSocket的其他方法和事件來實現更復雜的功能。


WebSocket的真實使用場景

即時通訊:

WebSocket非常適合用于即時通訊應用,因為它能夠實現實時雙向通信。以下是一個簡單的即時聊天應用的代碼教程。

在客戶端(JavaScript):

// 創建WebSocket對象并指定服務器地址
var socket = new WebSocket("ws://example.com/socket");

// 監聽連接建立事件
socket.onopen = function() {
console.log("WebSocket連接已建立");


// 監聽文本框輸入,按下Enter鍵時發送消息
var input = document.getElementById("input");
input.addEventListener("keyup", function(event) {
if (event.keyCode === 13) {
var message = input.value;
socket.send(message);
input.value = "";
}
});
};


// 監聽接收到服務器發送的消息
socket.onmessage = function(event) {
var message = event.data;
console.log("接收到服務器發送的消息:" + message);


// 將接收到的消息顯示在聊天窗口中
var chatWindow = document.getElementById("chatWindow");
chatWindow.innerHTML += "<p>" + message + "</p>";
};


// 監聽連接關閉事件
socket.onclose = function(event) {
console.log("WebSocket連接已關閉");
};


// 監聽連接錯誤事件
socket.onerror = function(event) {
console.error("WebSocket連接錯誤:" + event};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

在服務器端(示例使用Node.js):

const WebSocket = require("ws");

// 創建WebSocket服務器
const wss = new WebSocket.Server({ port: 8080 });


// 監聽連接建立事件
wss.on("connection", function(socket) {
console.log("WebSocket連接已建立");


// 監聽接收到客戶端發送的消息
socket.on("message", function(message) {
console.log("接收到客戶端發送的消息:" + message);


<span class="token comment">// 向所有連接的客戶端發送消息</span>
wss<span class="token punctuation">.</span>clients<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">client</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  client<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

});


// 監聽連接關閉事件
socket.on("close", function() {
console.log("WebSocket連接已關閉");
});
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在上述代碼中,客戶端通過創建WebSocket對象連接到服務器。輸入框中的文本框用于錄入要發送的消息,按下Enter鍵時會將消息發送給服務器。服務器接收到消息后,通過遍歷所有連接的客戶端,向每個客戶端發送消息。

這樣,多個客戶端就可以實時地進行聊天,并且所有的消息都會實時地在各個客戶端之間同步顯示。

多人協作:

WebSocket還可用于多人協作應用,讓多個用戶可以實時地協同編輯文檔或畫布。以下是一個簡單的代碼教程。

在客戶端(JavaScript):

// 創建WebSocket對象并指定服務器地址
var socket = new WebSocket("ws://example.com/socket");

// 監聽連接建立事件
socket.onopen = function() {
console.log("WebSocket連接已建立");


// 監聽文本框輸入,按下Enter鍵時發送繪畫指令
var canvas = document.getElementById("canvas");
canvas.addEventListener("mousedown", function(event) {
// 繪畫指令的數據格式可以自定義,這里使用了簡單的示例
var instruction = {
type: "draw",
position: {
x: event.clientX,
y: event.clientY
}
};
socket.send(JSON.stringify(instruction));
});
};


// 監聽接收到服務器發送的消息
socket.onmessage = function(event) {
var message = JSON.parse(event.data);
console.log("接收到服務器發送的消息:" + message);


// 根據消息執行相應的操作,示例中處理了繪畫指令
if (message.type === "draw") {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(message.position.x, message.position.y, 5, 0, 2 * Math.PI);
ctx.fill();
}
};


// 監聽連接關閉事件
socket.onclose = function(event) {
console.log("WebSocket連接已關閉");
};


// 監聽連接錯誤事件
socket.onerror = function(event) {
console.error("WebSocket連接錯誤:" + event};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

在服務器端(示例使用Node.js):

const WebSocket = require("ws");

// 創建WebSocket服務器
const wss = new WebSocket.Server({ port: 8080 });


// 監聽連接建立事件
wss.on("connection", function(socket) {
console.log("WebSocket連接已建立");


// 監聽接收到客戶端發送的消息
socket.on("message", function(message) {
console.log("接收到客戶端發送的消息:" + message);


<span class="token comment">// 向所有連接的客戶端發送消息</span>
wss<span class="token punctuation">.</span>clients<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">client</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  client<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

});


// 監聽連接關閉事件
socket.on("close", function() {
console.log("WebSocket連接已關閉");
});
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在上述代碼中,客戶端通過創建WebSocket對象連接到服務器。當鼠標在畫布上按下時,將繪畫指令發送給服務器。服務器接收到繪畫指令后,將指令廣播給所有連接的客戶端,并在各個客戶端上進行繪畫操作。

這樣,多個用戶就可以實時地協同編輯同一個畫布或文檔,所有的繪畫指令都會即時同步在各個客戶端之間。

實時數據更新:

WebSocket還可以用于實時數據更新應用,例如股票交易應用中的實時股票價格更新。以下是一個簡單的代碼教程。

在客戶端(JavaScript):

// 創建WebSocket對象并指定服務器地址
var socket = new WebSocket("鏈接");

// 監聽連接建立事件
socket.onopen = function() {
console.log("WebSocket連接已建立");
};


// 監聽接收到服務器發送的消息
socket.onmessage = function(event) {
var message = JSON.parse(event.data);
console.log("接收到服務器發送的消息:" + message);


// 對接收到的實時數據進行處理
var stockPriceElement = document.getElementById("stockPrice");
stockPriceElement.innerText = message.price;
};


// 監聽連接關閉事件
socket.onclose = function(event) {
console.log("WebSocket連接已關閉");
};


// 監聽連接錯誤事件
socket.onerror = function(event) {
console.error("WebSocket連接錯誤:" + event};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在服務器端(示例使用Node.js):

const WebSocket = require("ws");

// 創建WebSocket服務器
const wss = new WebSocket.Server({ port: 8080 });


// 模擬實時股票價格更新
setInterval(function() {
var stockPrice = Math.random() * 100;


// 向所有連接的客戶端發送實時數據
wss.clients.forEach(function(client) {
var data = {
price: stockPrice
};
client.send(JSON.stringify(data));
});
}, 2000);


// 監聽連接建立事件
wss.on("connection", function(socket) {
console.log("WebSocket連接已建立");


// 初始化發送實時數據
var stockPrice = Math.random() * 100;
var data = {
price: stockPrice
};
socket.send(JSON.stringify(data));


// 監聽連接關閉事件
socket.on("close", function() {
console.log("WebSocket連接已關閉");
});
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

在上述代碼中,客戶端通過創建WebSocket對象連接服務器。服務器使用setInterval函數模擬實時股票價格的更新,并將更新的數據發送給所有連接的客戶端??蛻舳吮O聽接收到服務器發送的消息,并處理接收到的實時數據。

這樣,在股票交易應用中,多個用戶可以實時地接收和顯示股票價格的更新信息。包括打游戲的時候,隊友之間互相溝通,打字交流,或者走位,放技能等等,都是即時的。


WebSocket的優勢與局限性

  • WebSocket的優勢:
  • 雙向實時通信:WebSocket提供了雙向的實時信能力,客戶端和服務器可以通過該協議進行雙向數據傳輸,實時反饋更新信息,實現即時通訊、實時數據推送等功能。

  • 較低的延遲:與傳統的HTTP請求相比,WebSocket降低了通信的開銷,減少了傳輸和處理數據的延遲,因此可以更快進行實時數據傳輸。

  • 更高的性能:由于WebSocket使用較少的頭部信息和更有效的消息傳輸格式,因此在相同帶寬下可以傳輸更多的數據,提高了性能和效率。

  • 廣泛的瀏覽器支持:WebSocket是HTML5的一部分,并且得到了大多數現代瀏覽器的支持,因此它可以在各種平臺和設備上使用。

  • 連接保持:與傳統的HTTP請求不同,WebSocket連接保持在建立之后,雙方可以隨時進行數據傳輸,避免了不必要的連接和斷開操作。

  • WebSocket的局限性:
  • 兼容性問題:雖然現代瀏覽器廣泛支持WebSocket,但在某些舊版本或特定設備上可能存在兼容性問題。為了兼容性,可以使用輪訓技術(如長輪詢)作為備選方案。

  • 部署和維護復雜性:WebSocket服務器的設置和配置可能比傳統的Web服務器復雜一些,需要專門的服務器環境和配置。

  • 安全性問題:由于WebSocket是在HTTP協議的基礎上建立的,它們共享相同的安全風險,例如跨站點腳本(XSS)和跨站請求偽造(CSRF)。因此,在使用WebSocket時需要考慮到安全性,并采取適當的安全措施。

  • 擴展問題:WebSocket協議還不支持像HTTP/2那樣的一些高級特性,例如頭部壓縮和流量控制。在某些特殊情況下,可能需要通過其他方式實現這些功能。

盡管WebSocket具有上述局限性,但它仍然是實時通訊、實時數據傳輸和實時協作等場景下的首選協議,因為它具備了雙向實時通信和較低延遲等一系列的優勢。在開發時,需要根據具體需求和限制,綜合考慮使用WebSocket的適用性。


結論

WebSocket是一種能夠提供雙向實時通信的協議,適用于需要實時數據傳輸和雙向通信的場景。它具有較低的延遲、更高的性和廣泛的瀏覽器持等優勢,能夠實現即時通訊、多人協和實時數據更新等功能。

然而,WebSocket也存在兼容性、部署和維護復雜性、安全性問題以及缺乏一些高級特性等局限性。在開發時,需要仔細考慮具體需求和限制,并必要時采取適當的解決方案。

總的來說,WebSocket在實時通信和實時數據傳輸方面具有明顯的優勢,是構建現代Web應用的重要工具之一。

藍藍設計(m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的大數據可視化界面設計、B端界面設計、桌面端界面設計、APP界面設計圖標定制、用戶體驗設計、交互設計、UI咨詢、高端網站設計、平面設計,以及相關的軟件開發服務,咨詢電話:01063334945。

關鍵詞:UI咨詢、UI設計服務公司軟件界面設計公司、界面設計公司、UI設計公司、UI交互設計公司、數據可視化設計公司用戶體驗公司、高端網站設計公司

銀行金融軟件UI界面設計、能源及監控軟件UI界面設計氣象行業UI界面設計、軌道交通界面設計地理信息系統GIS UI界面設計、航天軍工軟件UI界面設計醫療行業軟件UI界面設計、教育行業軟件UI界面設計企業信息化UI界面設計、軟件qt開發、軟件wpf開發、軟件vue開發

Vue2 watch監聽props的值

前端達人

再次遇到監聽子組件收到父組件傳過來的值,如果這個值變化,頁面中的值發現是不會跟著同步變化的。所以監聽props中的值,一直監聽。

 

代碼:

 
  1.  
    props: {
  2.  
    start:{
  3.  
    type: String,
  4.  
    },
  5.  
    end:{
  6.  
    type: String,
  7.  
    }
  8.  
    },
 

 

 
  1.  
    computed:{
  2.  
    myStart:function(){
  3.  
    return this.start
  4.  
    },
  5.  
    myEnd:function(){
  6.  
    return this.end
  7.  
    }
  8.  
    },
  9.  
    watch: {
  10.  
    myStart:function(newVal){
  11.  
    if(newVal){
  12.  
    this.startTime=newVal
  13.  
    }
  14.  
    },
  15.  
    myEnd:function(newVal){
  16.  
    if(newVal){
  17.  
    this.endTime=newVal
  18.  
    }
  19.  
    },
  20.  

藍藍設計(m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的大數據可視化界面設計B端界面設計、桌面端界面設計、APP界面設計、圖標定制、用戶體驗設計、交互設計、UI咨詢、高端網站設計、平面設計,以及相關的軟件開發服務,咨詢電話:01063334945。

關鍵詞:UI咨詢、UI設計服務公司、軟件界面設計公司、界面設計公司、UI設計公司、UI交互設計公司數據可視化設計公司、用戶體驗公司高端網站設計公司

銀行金融軟件UI界面設計、能源及監控軟件UI界面設計、氣象行業UI界面設計、軌道交通界面設計、地理信息系統GIS UI界面設計、航天軍工軟件UI界面設計醫療行業軟件UI界面設計、教育行業軟件UI界面設計企業信息化UI界面設計、軟件qt開發軟件wpf開發、軟件vue開發

什么是前端安全性(front-end security)?列舉一些前端安全性的最佳實踐

前端達人

前端入門之旅:探索Web開發的奇妙世界 歡迎來到前端入門之旅!感興趣的可以訂閱本專欄哦!這個專欄是為那些對Web開發感興趣、剛剛踏入前端領域的朋友們量身打造的。無論你是完全的新手還是有一些基礎的開發者,這里都將為你提供一個系統而又親切的學習平臺。在這個專欄中,我們將以問答形式每天更新,為大家呈現精選的前端知識點和常見問題解答。通過問答形式,我們希望能夠更直接地回應讀者們對于前端技術方面的疑問,并且幫助大家逐步建立起一個扎實的基礎。無論是HTML、CSS、JavaScript還是各種常用框架和工具,我們將深入淺出地解釋概念,并提供實際案例和練習來鞏固所學內容。同時,我們也會分享一些實用技巧和最佳實踐,幫助你更好地理解并運用前端開發中的各種技術。

無論你是尋找職業轉型、提升技能還是滿足個人興趣,我們都將全力以赴,為你提供最優質的學習資源和支持。讓我們一起探索Web開發的奇妙世界吧!加入前端入門之旅,成為一名出色的前端開發者! 讓我們啟航前端之旅?。。?/strong>


前端安全性概述及最佳實踐

前端安全性是指在前端開發中采取的一系列措施,旨在保護應用程序、用戶數據以及用戶隱私免受各種安全威脅。以下是一些前端安全性的最佳實踐:

  1. HTTPS 使用:

    • 使用HTTPS協議確保數據在傳輸過程中的加密,防止中間人攻擊。
  2. 內容安全策略(CSP):

    • 使用CSP來限制瀏覽器加載頁面中的資源,防止惡意腳本注入。
  3. 跨站腳本攻擊(XSS)防護:

    • 對用戶輸入和動態生成的內容進行合適的轉義或編碼。
    • 使用HTTP Only 標記來防止腳本操作 cookie。
  4. 跨站請求偽造(CSRF)防護:

    • 使用合適的令牌(CSRF Token)來驗證請求的合法性。
  5. 安全的跨域資源共享(CORS)配置:

    • 限制允許訪問資源的域,防止不受信任的域發起請求。
  6. 安全的第三方庫和框架:

    • 使用官方版本的庫和框架,避免使用已知的有安全漏洞的版本。
  7. 安全的存儲和傳輸:

    • 避免在前端存儲敏感信息,如密碼,而應交由后端進行處理。
    • 在數據傳輸時使用加密算法,確保數據在傳輸過程中的保密性。
  8. 用戶身份驗證和授權:

    • 使用安全的身份驗證方法,如OAuth或OpenID Connect。
    • 僅在有必要的情況下授予用戶特定的權限。
  9. 不使用過期或不安全的特性:

    • 避免使用已經過時或不再維護的前端框架和庫。
    • 避免使用不安全的瀏覽器特性,如棄用的插件。
  10. 前端路由安全:

    • 使用前端路由時,確保路由的訪問權限得到合理管理,防止越權訪問。
  11. 監測和報告安全事件:

    • 集成日志記錄和監控機制,及時發現異常行為。
    • 實現安全事件報告,以便及時采取措施應對攻擊。
  12. 教育和培訓:

    • 對開發團隊進行安全性培訓,提高對潛在威脅的認識。
    • 定期進行代碼審查,確保代碼符合最佳安全實踐。
  13. 安全頭部的使用:

    • 使用HTTP頭部來加強安全性,如Strict-Transport-Security(HSTS)。
  14. 定期進行安全性測試:

    • 進行定期的安全性測試,包括靜態代碼分析和滲透測試,以確保發現和修復潛在的安全漏洞。

這些最佳實踐有助于構建更加安全、可靠的前端應用程序,減少潛在的攻擊風險。前端安全性是一個不斷演變的領域,開發者應該時刻關注新的安全威脅和最佳實踐。


 

本專欄適用讀者比較廣泛,適用于前端初學者;或者沒有學過前端對前端有興趣的伙伴,亦或者是后端同學想在面試過程中能夠更好的展示自己拓展一些前端小知識點,所以如果你具備了前端的基礎跟著本專欄學習,也是可以很大程度幫助你查漏補缺,由于博主本人是自己再做內容輸出,如果文中出現有瑕疵的地方各位可以通過主頁的左側聯系我,我們一起進步,與此同時也推薦大家幾份專欄,有興趣的伙伴可以訂閱一下:除了下方的專欄外大家也可以到我的主頁能看到其他的專欄;

前端小游戲(免費)這份專欄將帶你進入一個充滿創意和樂趣的世界,通過利用HTML、CSS和JavaScript的基礎知識,我們將一起搭建各種有趣的頁面小游戲。無論你是初學者還是有一些前端開發經驗,這個專欄都適合你。我們會從最基礎的知識開始,循序漸進地引導你掌握構建頁面游戲所需的技能。通過實際案例和練習,你將學會如何運用HTML來構建頁面結構,使用CSS來美化游戲界面,并利用JavaScript為游戲添加交互和動態效果。在這個專欄中,我們將涵蓋各種類型的小游戲,包括迷宮游戲、打磚塊、貪吃蛇、掃雷、計算器、飛機大戰、井字游戲、拼圖、迷宮等等。每個項目都會以簡潔明了的步驟指導你完成搭建過程,并提供詳細解釋和代碼示例。同時,我們也會分享一些優化技巧和最佳實踐,幫助你提升頁面性能和用戶體驗。無論你是想尋找一個有趣的項目來鍛煉自己的前端技能,還是對頁面游戲開發感興趣,前端小游戲專欄都會成為你的最佳選擇

Vue3通透教程【從零到一】(付費) 歡迎來到Vue3通透教程!這個專欄旨在為大家提供全面的Vue3相關技術知識。如果你有一些Vue2經驗,這個專欄都能幫助你掌握Vue3的核心概念和使用方法。我們將從零開始,循序漸進地引導你構建一個完整的Vue應用程序。通過實際案例和練習,你將學會如何使用Vue3的模板語法、組件化開發、狀態管理、路由等功能。我們還會介紹一些高級特性,如Composition API和Teleport等,幫助你更好地理解和應用Vue3的新特性。在這個專欄中,我們將以簡潔明了的步驟指導你完成每個項目,并提供詳細解釋和示例代碼。同時,我們也會分享一些Vue3開發中常見的問題和解決方案,幫助你克服困難并提升開發效率。無論你是想深入學習Vue3或者需要一個全面的指南來構建前端項目,Vue3通透教程專欄都會成為你不可或缺的資源。

TypeScript入門指南(免費) 是一個旨在幫助大家快速入門并掌握TypeScript相關技術的專欄。通過簡潔明了的語言和豐富的示例代碼,我們將深入講解TypeScript的基本概念、語法和特性。無論您是初學者還是有一定經驗的開發者,都能在這里找到適合自己的學習路徑。從類型注解、接口、類等核心特性到模塊化開發、工具配置以及與常見前端框架的集成,我們將全面覆蓋各個方面。通過閱讀本專欄,您將能夠提升JavaScript代碼的可靠性和可維護性,并為自己的項目提供更好的代碼質量和開發效率。讓我們一起踏上這個精彩而富有挑戰性的TypeScript之旅吧!

 

藍藍設計(m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的大數據可視化界面設計、B端界面設計、桌面端界面設計APP界面設計、圖標定制、用戶體驗設計、交互設計、UI咨詢、高端網站設計、平面設計,以及相關的軟件開發服務,咨詢電話:01063334945。

關鍵詞:UI咨詢、UI設計服務公司、軟件界面設計公司、界面設計公司、UI設計公司、UI交互設計公司、數據可視化設計公司、用戶體驗公司高端網站設計公司

銀行金融軟件UI界面設計、能源及監控軟件UI界面設計氣象行業UI界面設計、軌道交通界面設計、地理信息系統GIS UI界面設計、航天軍工軟件UI界面設計醫療行業軟件UI界面設計、教育行業軟件UI界面設計企業信息化UI界面設計、軟件qt開發軟件wpf開發、軟件vue開發

前端學習大綱

前端達人

第一階段:

  • HTML+CSS:

HTML進階、CSS進階、div+css布局、HTML+css整站開發、

  • JavaScript基礎:

Js基礎教程、js內置對象常用方法、常見DOM樹操作大全、ECMAscript、DOM、BOM、定時器和焦點圖。

  • JS基本特效:

常見特效、例如:tab、導航、整頁滾動、輪播圖、JS制作幻燈片、彈出層、手風琴菜單、瀑布流布局、滾動事件、滾差視圖。

  • JS高級特征:

正則表達式、排序算法、遞歸算法、閉包、函數節流、作用域鏈、基于距離運動框架、面向對象基礎、

  • JQuery:基礎使用

懸著器、DOM操作、特效和動畫、方法鏈、拖拽、變形、JQueryUI組件基本使用。

第二階段:HTML5和移動Web開發

  • HTML5:

HTML5新語義標簽、HTML5表單、音頻和視頻、離線和本地存儲、SVG、Web Socket、Canvas.

  • CSS3:

CSS3新選擇器、偽元素、臉色表示法、邊框、陰影、background系列屬性改變、Transition、動畫、景深和深透、3D效果制作、Velocity.js框架、元素進場、出場策略、炫酷CSS3網頁制作。

  • Bootstrap:

響應式概念、媒體查詢、響應式網站制作、刪格系統、刪格系統原理、Bootstrap常用模板、LESS和SASS。

  • 移動Web開發:

跨終端WEB和主流設備簡介、視口、流式布局、彈性盒子、rem、移動終端JavaScript事件、手機中常見JS效果制作、Zepto.js、手機聚劃算頁面、手機滾屏。

第三階段:HTTP服務和AJAX編程

  • WEB服務器基礎:

服務器基礎知識、Apache服務器和其他WEB服務器介紹、Apache服務器搭建、HTTP介紹。

  • PHP基礎:

PHP基礎語法、使用PHP處理簡單的GET或者POST請求、

  • AJAX上篇:

Ajax簡介和異步的概念、Ajax框架的封裝、XMLHttpRequest對象詳細介紹方法、兼容性處理方法、Ajax框架的封裝、Ajax中緩存問題、XML介紹和使用。

  • AJAX下篇:

JSON和JSON解析、數據綁定和模板技術、JSONP、跨域技術、圖片預讀取和lazy-load技術、JQuery框架中的AjaxAPI、使用Ajax實現爆布流案例額。

第四階段:面向對象進階

  • 面向對象終極篇:

從內存角度到理解JS面向對象、基本類型、復雜類型、原型鏈、ES6中的面向對象、屬性讀寫權限、設置器、訪問器。

  • 面向對象三大特征:

繼承性、多態性、封裝性、接口。

  • 設計模式:

面向對象編程思維、單例模式、工廠模式、策略模式、觀察者模式、模板方法模式、代理模式、裝飾者模式、適配器模式、面向切面編程。

第五階段:封裝一個屬于自己的框架

  • 框架封裝基礎:

事件流、冒泡、捕獲、事件對象、事件框架、選擇框架。

  • 框架封裝中級:

運動原理、單物體運動框架、多物體運動框架、運動框架面向對象封裝。

  • 框架封裝高級和補充:

JQuery框架雛形、可擴展性、模塊化、封裝屬于傳智自己的框架。

第六階段:模塊化組件開發

  • 面向組件編程:

面向組件編程的方式、面向組件編程的實現原理、面向組件編程實戰、基于組件化思想開發網站應用程序。

  • 面向模塊編程:

AMD設計規范、CMD設計規范、RequireJS,LoadJS、淘寶的SeaJS。

第七階段:主流的流行框架

  • Web開發工作流:

GIT/SVN、Yeoman腳手架、NPM/Bower依賴管理工具、Grunt/Gulp/Webpack。

  • MVC/MVVM/MVW框架:

Angular.js、Backbone.js、Knockout/Ember。

  • 常用庫:

React.js、Vue.js、Zepto.js。

第八階段:HTML5原生移動應用開發

  • Cordova:

WebApp/NativeApp/HybirdApp簡介、Cordova簡介、與PhoneGap之間的關系、開發環境搭建、Cordova實戰(創建項目,配置,編譯,調試,部署發布)。

  • Ionic:

Ionic簡介和同類對比、模板項目解析、常見組件及使用、結合Angular構建APP、常見效果(下拉刷新,上拉加載,側滑導航,選項卡)。

  • React Native:

React Native簡介、React Native環境配置、創建項目,配置,編譯,調試,部署發布、原生模塊和UI組件、原生常用API。

  • HTML5+:

HTML5+中國產業聯盟、HTML5 Plus Runtime環境、HBuilder開發工具、MUI框架、H5+開發和部署。

第九階段:   Node.js全棧開發:

  • 快速入門:

Node.js發展、生態圈、Io.js、Linux/Windows/OS X環境配置、REPL環境和控制臺程序、異步編程,非阻塞I/O、模塊概念,模塊管理工具、開發流程,調試,測試。

  • 核心模塊和對象:

全局對象global,process,console,util、事件驅動,事件發射器、加密解密,路徑操作,序列化和反序列化、文件流操作、HTTP服務端與客戶端、Socket.IO。

  • Web開發基礎:

HTTP協議,請求響應處理過程、關系型數據庫操作和數據訪問、非關系型數據庫操作和數據訪問、原生的Node.js開發Web應用程序、Web開發工作流、Node.js開發Blog案例。

  • 快速開發框架:

Express簡介+MVC簡介、Express常用API、Express路由模塊、Jade/Ejs模板引擎、使用Express重構Blog案例、Koa等其他常見MVC框架。

  • Node.js開發電子商務實戰:

需求與設計、賬戶模塊注冊登錄、會員中心模塊、前臺展示模塊、購物車,訂單結算、在線客服即時通訊模塊。

日歷

鏈接

個人資料

藍藍設計的小編 http://m.skdbbs.com

存檔

92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线
亚洲精品国久久99热| 台湾色综合娱乐中文网| 热久久免费国产视频| 欧美理论视频| 日本在线免费网| 亚洲综合二区| 国产偷国产偷亚洲高清人白洁| 日本欧美国产在线| 天天躁日日躁成人字幕aⅴ| 成人动漫在线视频| 久久手机精品视频| 婷婷久久综合九色综合99蜜桃| 亚洲图片在区色| 宅男在线一区| 国产.精品.日韩.另类.中文.在线.播放| 国产日韩欧美一区二区三区四区| 亚洲欧美激情视频在线观看一区二区三区| 成人性色生活片| 国产精品99久久久久久久vr| 久久毛片亚洲| 欧美激情五月| а√天堂中文在线资源bt在线| 亚洲第一福利视频| 秋霞影院午夜丰满少妇在线视频| 亚洲a∨精品一区二区三区导航| 国产精品扒开腿做爽爽爽男男| 欧美mv日韩mv国产网站| 欧洲日韩成人av| 美女撒尿一区二区三区| 久久久天堂国产精品女人| 亚洲国产中文字幕久久网| 国产精品手机在线| 国产精选一区二区三区| 韩国成人二区| www.成人在线| 欧美hdxxx| 亚洲高清免费观看高清完整版在线观看| 美女诱惑一区二区| 97se亚洲国产综合自在线不卡| 亚洲成人av电影在线| 日韩成人性视频| 91美女视频网站| 亚洲丝袜另类动漫二区| 三级一区在线视频先锋| 日本精品视频一区| 一区二区成人在线| 国产精品毛片一区二区在线看| 99精品久久久久久| 久久av网址| 51精品在线| 99re国产视频| 岛国av免费在线观看| 亚洲欧美中文日韩在线v日本| 久久久电影免费观看完整版| 亚洲国产精品一区二区第一页| 岛国大片在线观看| 日韩精品一区二区三区四区视频| 久久综合伊人77777蜜臀| 亚洲黄色av女优在线观看| 一区二区在线观看不卡| 97在线精品国自产拍中文| 久久99国产精品久久99果冻传媒| 夜夜嗨av一区二区三区四季av| 在线视频欧美日韩| 亚洲午夜久久久久久久久久久| 久久久999精品免费| 最近中文字幕日韩精品| 亚洲国产精品yw在线观看| 国产精品日日摸夜夜添夜夜av| 国产精品精品国产一区二区| 欧美视频在线免费看| 在线观看一区二区精品视频| 欧美挤奶吃奶水xxxxx| 国产+成+人+亚洲欧洲| 欧美第一黄网免费网站| 少女频道在线观看免费播放电视剧| 国产精品都在这里| www.亚洲免费| 久久久国产成人精品| 美美哒免费高清在线观看视频一区二区| 韩日一区二区| 日本一区视频在线观看免费| 久久伊人精品一区二区三区| 香蕉久久夜色| 欧美热在线视频精品999| 蜜桃a∨噜噜一区二区三区| 国产欧美日韩精品一区二区免费| av电影高清在线观看| 亚洲女同女同女同女同女同69| 日韩电视剧免费观看网站| 8x国产一区二区三区精品推荐| 久热成人在线视频| 精品国产一区二区亚洲人成毛片| 天堂资源在线亚洲视频| 亚洲精品久久嫩草网站秘色| 欧美性生交xxxxxdddd| 国产小视频91| 国产成人精品日本亚洲| 波多野结衣在线aⅴ中文字幕不卡| jk漫画禁漫成人入口| 粉嫩aⅴ一区二区三区四区五区| 欧美日韩一二区| 素人一区二区三区| 伊人精品影院| 欧美怡春院一区二区三区| 色综合久久中文综合久久牛| 日韩一区二区欧美| 国产精品一区而去| 在线欧美不卡| 日本免费中文字幕在线| 午夜日韩在线电影| 午夜激情视频在线| 成人影院网站ww555久久精品| 国内外成人免费激情在线视频| 欧美日韩国产一中文字不卡| 91亚洲成人| 欧美色就是色| 国产麻豆一区二区三区| 一本到不卡免费一区二区| 久久一本综合频道| 青草成人免费视频| 小嫩嫩12欧美| 婷婷激情在线| 亚洲成人看片| 国内精品400部情侣激情| 亚洲1区在线| 99国产**精品****| 亚洲免费影视第一页| 91久久夜色精品国产网站| 国产亚洲精品一区二区| 欧美成年人视频网站欧美| 亚洲天天在线日亚洲洲精| 91精品婷婷国产综合久久蝌蚪| 成人在线视频网| 亚洲福利一区| 欧美极品美女视频| 欧美特黄级在线| 国内精品久久久久久久影视麻豆| 91原创国产| 国产一区二区三区日韩欧美| 婷婷一区二区三区| 精品欠久久久中文字幕加勒比| 久久亚洲一区二区三区四区| 松下纱荣子在线观看| 综合色一区二区| 国产成人女人毛片视频在线| 欧美日韩另类丝袜其他| 久久久久久久久四区三区| 51午夜精品国产| 午夜视频在线看| 自由日本语热亚洲人| 欧美激情视频一区二区三区不卡| 国产精品99久久久久久久久久久久| 电影午夜精品一区二区三区| 亚洲人成777| 成人福利视频在线| 国产亚洲精品7777| 欧美日韩破处视频| 最新中文字幕在线播放| 日韩美女国产精品| 亚洲三级观看| 国产麻豆精品theporn| 日本视频在线一区| 亚洲理伦在线|