イオンフレームワークから市場(よく並べ替え)パート1


編集者


ようこそ戻る、貼り付けのおかげで、この部分は、エディタに正直にそのエディタよりも多くのVueに焦点を当て、我々はいくつかのコンポーネントを設定し、論理的なルーティング、ローカルストレージとポストの要求を実装する単純なサーバーに.
注:この部分のコードがたくさんあるので、私は記事の一番下にファイルに従ってすべてのコードを投稿します

ヘッダーコンポーネント


コンポーネントの下にヘッダーを作成します.VUE、このコンポーネントは、基本的にアプリケーションのメインウィンドウに表示されるものを決定します.Vue
三つのタグを作る

<template>


</template>

<script>
export default{
  name: "Header"


}


</script>




インポートヘッダー.アプリにVue.Vueと削除
アプリ.Vue

<template>
   <Header/>

</template>

<script>
import Header from "./components/Header.vue";
export default{
  name: "App",
  components: {
    Header
  }


}


</script>

<style scoped>




.container{

 padding: .4em 1em;

 }




</style>


これはどのように新しいアプリです.Vueはセットアップです、エディタは消えるべきです、そして、現在、我々は空のウインドウを持っています.
現在、ヘッダーはappの子です.Vueとルーティングにも責任があり、親コンポーネントと通信する方法が必要です.

App.vue
   Header.vue 




これはアプリケーションの子としてヘッダーがどのように見えるかです.vue、emitは、子要素が親にシグナルを送ることができ、親がシグナルをキャッチすることができます.
我々は家、エディタ、およびジョブボードを持っているヘッダーでは、我々はアプリに信号を送信するためにこれらの3つのヘッダーのいずれかをクリックして欲しい.ボタンをクリックしたので、アプリをクリックした.Vueは関連するコンポーネントを表示します.
しかし、VUEから直接エディタコンポーネントを表示したくない.アプリケーションは、テンプレートを削除するように、テンプレートを削除するようにテンプレートを管理する必要がありますので、エディタは、管理コンポーネントの子、最終的には、このように構造が表示されます

App.vue 
  Header.vue
  Home.vue 
  EditorManage.vue 
        Editor.vue


他の2つのコンポーネントのホームを作成し、コンポーネントフォルダ内で管理(EditorManager)、我々はすでにエディタを持っています.VUE我々はコンポーネントを管理するから移動します.
ヘッダに戻る

<template>

 <div class="header">

     <div>

       <h1>Logo</h1>

     </div>



     <nav>



         <ul>

         <!-- emitting a signal called Header, with a prop  -->
         <li @click="$emit('Header', 'Home')" >Home</li>

         <li @click="$emit('Header', 'Editor')">Editor</li>

         <li>Job Board</li>

         </ul> 

     </nav>

  </div>

</template>





<script>

export default {

 name: "Header" 



}

</script>

今のところ、我々は空のコンポーネントであり、この記事のための私達の焦点を管理するセットアップホーム
emitがちょうど関数であるのを見ることができるように、最初の変数「ヘッダー」はシグナルの名前です、そして、親コンポーネントはそれが火であるときはいつでも、この名前を使って信号を捕えます.
シグナル名が通常のパラメータに続くと、この場合、文字列を渡します
"$emit('Header', 'Home')"
私たちは基本的な色をコンポーネントにスタイルを使用します、ちょうど私たちが何をしているかを見ることができるように、私が以前のポストで言及したように、私はCSSをそれほど説明しません.
ヘッダ用のCSS
<template>
  ....
</template>


<script>

export default {

 name: "Header" 



}

</script>


//css

<style scoped>

 .header {

 display:flex;

 justify-content: space-between;

 color: white;

 background-color: black;

 margin-bottom: 2em;



 } 



 .header h1 {

 padding-left: 1em;

 }



 .header nav ul {

 display: flex;

 margin: 1em 3em;

 }



 .header nav ul li {

 padding: 1em 2em;

 list-style: none;



 }



 li:hover{

 cursor: pointer;

 }



</style>



これは基本的なスタイルを

シグナルのキャッチとハンドリング


アプリで.Vueはヘッダー信号を処理します、それは非常に簡単です、あなたはPropのような発射成分の信号の名前を通過して、定義して、信号を処理するために機能を割り当てます、あるいは、信号が発射されるとき、実行するために
  @name-of-the-signal = "handlingFunction"

アプリで.Vue
<template>
      <!--  handling the signal fired by heard, which executes navigate() -->
     <Header @Header="navigate"/>

</template>




vueはdataを使ってdataを返します.data ()はdataを使ってオブジェクトを返します.このデータはコンポーネントの状態として考え、コンポーネントのどこかにアクセスできます.Paramルートをナビゲート(ルート)関数に渡すと、ルートはEMIT関数で渡された値と等しくなります.


</template>



<script>


import Header from "./components/Header.vue";





export default {

 name: "App",

 components: {

 Header

 },

 methods: {

     navigate(route){

        this.display = route

     }

 },




 data(){

     return{


 // has a default value of Home, so on enter the app always show the home component
        display: "Home"

     }

 }

};

</script>

ホームをインポートし、アプリケーションにコンポーネントを管理します.Vue


<script>



import Header from "./components/Header.vue";

import Home from "./components/Home.vue";

import Manage from "./components/EditorManager.vue";



export default {

 name: "App",

 components: {

 Header,

 Home,

 Manage

 },
...

};

</script>

表示varを更新するたびに、テンプレートで条件付きルーティングを設定しましょう.ユーザーがナビゲートしているという意味で、コンポーネントは更新されます
アプリで.Vue
<template>

    <div class="container">


     <!-- header is always rendered -->
     <Header @Header="navigate"/>


     <!-- Manage will render if the display var === string Editor -->
    <div v-if="display === 'Editor'">



          <Manage/>

    </div>


      <!-- so does home, this is called conditional rendering, v-if same as if -->

    <div v-if="display === 'Home'">

        <Home/>

    </div>




</div>



</template>



私たちは、アプリ.Vueは完了です.
あなたは今“ルート”、または明示的に論理的にレンダリングする必要があります

コンポーネントの管理


で編集します.Vue
デフォルトの設定

<template>
   <div>


   </div>

</template>

<script>
export default{
  name: "Manage"

}


</script>

<style scoped>


</style>




まず、新しいテンプレートを追加する方法を必要とする、我々は、フローティングアクションボタン(Fab)を使用して、右下の場所、OnClickそれは、タイトルと字幕のサブタイトルを埋めるためにモーダルを開きます保存、また、それは同じボタンを閉じて同じボタンを開きます.
最初にモーダルコンポーネントを作成し、ファイルaddtempを呼び出して、テンプレートを追加し、コンポーネント自体を追加し、エディタの管理者にインポートし、以下のようにクラスモードでdivの内部で宣言すると、以下に示すように、data ()関数が必要です

<template>

 <div class="modal" v-if="showModal">


<!-- addTemplate is a signal coming from the Add component -->
       <Add @addTemplate="add"/> 

 </div>

</template>



<script>
import Add from "./AddTemp.vue"

//import the editor also
import Ed from "./Editor.vue"
 export default{
      name: "Manage",
      components: {
       Add,
       Ed

      }

 }

</script>


data ()


...
export default{
name: "Manage",
components:{
...
},

 data(){

     return{

         showModal: false,
     }

 },



}


のモードを切り替えるには、ボタンを作成してみましょう

 <template> 


<div>




    <div class="fab" @click="toggleModal">

       // show add when modal is closed
       <label v-if="!showModal">

           add

       </label> 
      //show close when modal is open

         <label v-if="showModal">

           close

         </label> 

     </div>


</div>


<div class="modal" v-if="showModal">
   ....

</div>
</template>

<script>
....

</script>


<style scoped>

  /*place the fab bottom right and make it black  */
   .fab{

 position: absolute;

 padding: 1em;

 background: black;

 color: white;

 bottom: 0;

 right: 0;

 margin: 1em;

 border-radius: 30px;

 /* right: 100%; */



 }


/* expand the fab on hover */
 .fab:hover {

 transition : transform 200ms ease-out;

 transform: scale(1.1, 1.2)



 }

 /* styles the modal, center it, give a box-shadow */

  .modal {

 position: absolute;

 top: 25%;

 width: 50%;

 transform: translateX(50%);

 display: flex;

 justify-content: center;

 box-shadow: 15px 15px 53px rgb(243, 244, 246);

 border-radius: .5em;



 max-height: 30em;

 background: lightblue;

 }


</style>
のロジックを追加しましょう


<script>
export default{
 ...,

 methods: {

     toggleModal(){
          //make showModal the opposite of itself
          //this will toggle the modal
         this.showModal = !this.showModal

    },

 }


}

</script>


ここでaddtempファイルを開き、デフォルトのタグで入力します.
テンプレートは、タイトルと字幕を受け入れる簡単なフォーム


<template>
 <div>

     <h4>Add Template</h4>



     <div class="form">

         <label>Title</label>

         <input v-model="title"/>

         <hr>

         <label>SubTitle</label>

         <input v-model="SubTitle"/>


         // submit the form by emitting a signal (the signal will be emitted in the addTemplate() function)
         <button @click="addTemplate()">Add</button>

     </div>



 </div>


</template>



V - Modelは、制御された要素と呼ぶものを作成します.単純に、ある状態にバインドされた要素を変更すると、コンポーネントが変更されます.入力では、data ()関数で定義するtitleとsubtitleをバインドします.

<script>


export default{
name: "Add",
 data(){
 //state(bound to the input elements)

     return {

             title: "", 

             SubTitle: ""

     }

}

</script>


データを準備し、管理するためにシグナリングテンプレートを保存することができます

<script>


export default{
name: "Add",
 data(){
...

}, 
methods: {

   addTemplate(){

        // get the form data
         const temp = {

             title: this.title,

             SubTitle: this.SubTitle

         }

     //signal and give EditorManager the temp data

    this.$emit("addTemplate", temp)

 },
}

</script>


<style scoped>

.form{

 width: 100%;

 display: grid;

 gap: .5em;




}



.form input{

 border: 2px solid black;

 width: 100%;

 height: 22px;

}



.form button{

 margin: 1em;

}


</style>
エディタマネージャーのシグナルとtempデータの取り扱い



<script>
...

//we will define these methods shortly
import {persist} from "../utillity/localPersist"

import {getTemps} from "../utillity/localPersist"


export default{

name: "Manage",
...,

methods: {

     add(template){

         console.log(template)

        // creating a numeric id
         template.id = this.templates.length + 1;

         // adding the new template to the existing ones
         this.templates = [...this.templates, template]

        // we will define shortly persist the data to localstorage(browser store)
         persist(this.templates)


    },



}


}


</script>



ユーティリティでlocalpersistファイルを作成し、次の機能を追加します

// persist data
export function persist(templates){



     try {
      // persist templates with key templates, and we are stringifying the    templates because localstorage can only store strings

     localStorage.setItem("templates", JSON.stringify(templates))

     } catch (error) {

     console.log(error) 

     }




} 


 // get template data 

export function getTemps(){



  // get string data and parsing back to object

   return JSON.parse(localStorage.getItem("templates"))

}


テンプレートデータを永続化するには、作成したメソッドを使用して保存したテンプレートを取得できます.
エディタで

export default{
name: "Manage",
data(){
...,
   templates: []

}, 
methods: {
....

//way to delete templates
 del(id) {


     // del a template given an id 
     this.templates.splice(id-1, 1)

     // save the new data
     persist(this.templates)



 },


}

created(){



// if not undefined || null
 if(getTemps()){


    // asigning templates to templates[]
   this.templates = getTemps();



 }

}

テンプレートとセットアップ、必要なボタンを視覚化しましょう
編集長

<template>

<div>


     <div class="templates">



              <!--looping over templates  -->


                  <!--:key - unique  -->
        <div v-for="template in templates" :key="template.title" class="template">

                         <div class="temp__text">

                         <h2>{{template.title}}</h2>

                         <h3>{{template.SubTitle}}</h3>

                         </div>


                         // each template controls
                         <div class="actions">

                            // will not implement in this article
                         <button @click="edit">Edit</button>


                         <button @click="del(template.id)">Del</button>

                           // open Ed to create the specified template
                         <button @click="openEditor(template)">Editor</button>




                         </div> 

         </div>




     </div> 





   <div class="fab">
   ....

   </div>

</div>


<div class="modal" ..>
....

</div>


</template>



テンプレート用のCSS



 .template {

 display: grid;

 grid-template-columns: 50% 50%;

 color: lightblue;




 }



 .temp__text {

 display: flex;

 padding: .5em;

 justify-content: space-around;

 }



.actions{

 display:flex;

 align-items: center;

}



.actions button {

 padding: .5em 1em;

 /* height: 1.5em; */

 margin-left: 1em;

 background: black;

 color: white;

 border-radius: 15px;

}



.actions button:hover {

transition: tranform 200ms ease-out;

 transform: scale(1.1, 1.2);

}




エディタを開く
セットアップ

<template>
    //v-if="!showEditor" === show the templates only when editor is closed 
    <div v-if="!showEditor">

     <div class="templates">
     ....
     </div>

     <div class="fab">
      ...
     </div>


    </div>

 <div class="modal" v-if="showModal">

 ...

 </div>



 <div v-if="showEditor">
      // showing editor, passing a boud props :data(which is the selected template)
      //@back signals back(when clicking a back button on Ed to close the Editor)
    <Ed @back="closeEd()" :data="temp"/>

 </div>



</template>


<script>



export default{
...,

data(){
    return {
    ..., 
    showEditor: false,

     temp: undefined,

    }
}, 
methods: {
..., 
 openEditor(template){
         // if the modal is opened close it
         if(this.showModal){

           this.toggleModal()

         }


          // the :data prop passed to Ed 
         this.temp = template;

        // show the editor
         this.showEditor = true;

    },
     // on signal back button on Ed close the editor
     closeEd(){

         window.editor = undefined;

         this.showEditor = false;

 },

}



}



これはすべて新しいコンポーネントのためです.
ホームコンポーネントについては、あなたが好きなものを作ることができる、私のためのWebアプリを使用する方法については簡単なチュートリアルです
エディタで.Vue少し変わった
まず最初に、追加されます:クラスEditorToolsとUPDATE小道具のdivの下の後ろのボタンは、タイプオブジェクト(選択されたテンプレートである)の支柱データを取るために

<template>
  <div class="editorTools">
  ..
  </div>
     <!--emit signal back which closes editor, back to manager  -->
    <button @click="$emit('back')" >Back</button>
     <!-- make the data prop text of h1 element(for now)-->
    <h1>{{ data }}</h1>

</template>



<script>

export default{
...,
props:{
  data: Object
 }, 


 methods: {

   save: function(){

      window.editor.save().then((data)=> {

         // publishing the data to the server
           let newB = {

             id: this.data.id,

             title: this.data.title,

             subtitle: this.data.SubTitle,

             data

             }


             // stringify
             let strData = JSON.stringify(newB)

             console.log(strData)

             console.log(newB)



             // posting to the local our simple save the published data

             fetch(`http://localhost:3000/temp/new/${strData}`, {method: "POST"}).then(res => {

             console.log(res.text().then(data => console.log(data)))

             })



    })

   }

 }



}

</script>



そして、それは今のところ、しかし、1つの最後のことに気づいた場合は、イメージを失敗してエディタを公開すると、ブラウザが許可されていないので、Base 64文字列が長いので、我々はイオンの前に、次の記事で解決するために、私はまだもう少しそれについて研究し、効率的な方法を見つける必要があります.
今のところは、テキストであり、それを発行するテンプレートを書くことができるため、ローカルサーバーが対応します.
私はローカルサーバーにいくつかの変更を行いました.

const express = require("express")
const jsonServer = require("json-server")



const app = express()


let Templates = {}


const router = jsonServer.router("db.json")
const middlewares = jsonServer.defaults()
const server = jsonServer.create()

server.use(middlewares)


server.get('/home', (req, res) => {
    res.jsonp({ user: 'tj' });
  })


server.get("/temp/:id", (req, res)=> {
  let {id} = req.params
  let getted = Templates[id]
  console.log(getted)

  res.jsonp({data: getted})
})  

server.post("/temp/new/:data", (req, res)=> {
  let {data} = req.params
  data = JSON.parse(data)
  Templates[data.id] = data
  console.log(Templates)
  console.log(data.data.blocks[0].data.img)
  res.status(200).jsonp(Templates);
} )

    // router.render = (req, res) => {
    //     res.jsonp({
    //       body: res.locals.data
    //     })
    //   }

server.use(router)
server.use(jsonServer.bodyParser)
server.use((req, res, next) => {
    if (req.method === 'POST') {
      req.body.createdAt = Date.now()
    }
    // Continue to JSON Server router
    next()
  })

server.listen(3000, ()=> {
    console.log(`listening on port ${3000}`)
})

すべてのコード
アプリ.Vue


<template>

<div class="container">



 <Header @Header="navigate"/>



<div v-if="display === 'Editor'">

 <!-- <Ed msg="Editor" /> -->

 <Manage/>

</div>




<div v-if="display === 'Home'">

 <Home/>

</div>





</div>



</template>



<script>

// import Ed from "./components/Editor.vue";

import Header from "./components/Header.vue";

import Home from "./components/Home.vue";

import Manage from "./components/EditorManager.vue";



export default {

 name: "App",

 components: {

 Header,

 Home,

 Manage

 },

 methods: {

     navigate(route){

     this.display = route

     }

 },




 data(){

         return{

         display: "Home"

         }

     }

};

</script>



<style scoped>




.container{

 padding: .4em 1em;

 }




</style>

ヘッダ.Vue


<template>

 <div class="header">

 <div>

 <h1>Logo</h1>

 </div>



 <nav>



 <ul>

 <li @click="$emit('Header', 'Home')" >Home</li>

 <li @click="$emit('Header', 'Editor')">Editor</li>

 <li>Job Board</li>

 </ul> 

 </nav>





 </div>

</template>





<script>

export default {

 name: "Header" 



}

</script>





<style scoped>

 .header {

 display:flex;

 justify-content: space-between;

 color: white;

 background-color: black;

 margin-bottom: 2em;



 } 



 .header h1 {

 padding-left: 1em;

 }



 .header nav ul {

 display: flex;

 margin: 1em 3em;

 }



 .header nav ul li {

 padding: 1em 2em;

 list-style: none;



 }



 li:hover{

 cursor: pointer;

 }



</style>


エディトマネージャー.Vue




<template>

 <div v-if="!showEditor">



 <div class="templates">

 <div v-for="template in templates" :key="template.title" class="template">

 <div class="temp__text">

 <h2>{{template.title}}</h2>

 <h3>{{template.SubTitle}}</h3>

 </div>



 <div class="actions">

 <button @click="edit">Edit</button>

 <button @click="del(template.id)">Del</button>

 <button @click="openEditor(template)">Editor</button>

 </div> 

 </div>




 </div>

 <div class="fab" @click="toggleModal">

 <label v-if="!showModal">

 add

 </label> 

 <label v-if="showModal">

 close

 </label> 

 </div> 




 </div>



 <div class="modal" v-if="showModal">

 <Add @addTemplate="add"/> 

 </div>



 <div v-if="showEditor">

 <Ed @back="closeEd()" :data="temp"/>

 </div>




</template>




<script>

import Add from "./AddTemp.vue"

import Ed from "./Editor.vue"

import {persist} from "../utillity/localPersist"

import {getTemps} from "../utillity/localPersist"



export default {

 name: "Manage",

 components: {

 Add,

 Ed

 },

 data(){

 return{

 showModal: false,

 showEditor: false,

 temp: undefined,

 templates: []

 }

 },

 methods:{

 toggleModal(){

 this.showModal = !this.showModal

 },

 closeEd(){

 window.editor = undefined;

 this.showEditor = false;

 },



 add(template){

 console.log(template)

 template.id = this.templates.length + 1;

 this.templates = [...this.templates, template]

 persist(this.templates)

 this.templates.forEach(val => {

 console.log(val.title)

 })

 },



 del(id) {



 this.templates.splice(id-1, 1)

 persist(this.templates)



 },

 edit(){



 },

 openEditor(template){

 if(this.showModal){

 this.toggleModal()

 }



 this.temp = template;

 this.showEditor = true;

 }




 },

 created(){

 console.log(getTemps())



 if(getTemps()){

 console.log("not und")

 this.templates = getTemps();



 }

 }

}

</script>



<style scoped>





 .fab{

 position: absolute;

 padding: 1em;

 background: black;

 color: white;

 bottom: 0;

 right: 0;

 margin: 1em;

 border-radius: 30px;

 /* right: 100%; */



 }



 .fab:hover {

 transition : transform 200ms ease-out;

 transform: scale(1.1, 1.2)



 }



 .modal {

 position: absolute;

 top: 25%;

 width: 50%;

 transform: translateX(50%);

 display: flex;

 justify-content: center;

 box-shadow: 15px 15px 53px rgb(243, 244, 246);

 border-radius: .5em;



 max-height: 30em;

 background: lightblue;

 }



 .template {

 display: grid;

 grid-template-columns: 50% 50%;

 color: lightblue;




 }



 .temp__text {

 display: flex;

 padding: .5em;

 justify-content: space-around;

 }



.actions{

 display:flex;

 align-items: center;

}



.actions button {

 padding: .5em 1em;

 /* height: 1.5em; */

 margin-left: 1em;

 background: black;

 color: white;

 border-radius: 15px;

}



.actions button:hover {

transition: tranform 200ms ease-out;

 transform: scale(1.1, 1.2);

}

 .templates{

 }

</style>



addtemp .Vue

<template>

 <div>

 <h4>Add Template</h4>



 <div class="form">

 <label >Title</label>

 <input v-model="title"/>

 <hr>

 <label>SubTitle</label>

 <input v-model="SubTitle"/>



 <button @click="addTemplate()">Add</button>

 </div>



 </div>




</template>





<script>

export default {

 name: "Add",

 props: {

 }, 



 data(){

 return {

 title: "", 

 SubTitle: ""

 }

 },

 methods: {

 addTemplate(){

 const temp = {

 title: this.title,

 SubTitle: this.SubTitle

 }



 this.$emit("addTemplate", temp)

 },

 } 

}

</script>




<style scoped>



.form{

 width: 100%;

 display: grid;

 gap: .5em;




}



.form input{

 border: 2px solid black;

 width: 100%;

 height: 22px;

}



.form button{

 margin: 1em;

}




</style>

それは今のところ、読書のおかげです.
次に、サーバーの問題を修正しますが、私はあなた自身でそれを修正することをお勧めしますし、イオンの部分を実装します
質問やHiは、最良の方法を言うにはTwitterです: