.gdpr{position: fixed; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.7);color: #333;z-index:9999999;line-height:1.3;height: 100vh;width: 100vw} .gdpr_w{padding: 2rem;background: #fff;max-width: 700px;width: 95%;margin: 5% auto;text-align: center;position:fixed;left: 0;right: 0;margin:10% auto;} .gdpr_t{margin-bottom:15px;} .gdpr_t h3{font-size: 30px;margin:0px 0 10px 0;} .gdpr_t p{font-size: 16px;line-height: 1.45;margin:0;} .gdpr_x {position: absolute; right: 24px; top: 16px; cursor:pointer;} .gdpr_yn{margin-top:10px;} .gdpr_yn form{display: inline;} .gdpr_yn button{background: #37474F;border: none;color: #fff;padding: 8px 30px;font-size: 13px;margin: 0 3px;} .gdpr_yn .gdpr_n{background: #fff;color: #222;border: 1px solid #999;} amp-consent{margin-left: 10px;top: 2px;width: auto;background: transparent;} .gdpr_fmi{ width:100%; font-size: 15px; line-height: 1.45; margin: 0; } #footer .gdpr_fmi span, .gdpr_fmi span { display: inline-block; } #footer .gdpr_fmi a{ color: #005be2; } @media(max-width:768px){ .gdpr_w{width: 85%;margin:0 auto;padding:1.5rem;} } @media(max-width:700px){ .gdpr_w{margin:0 auto; width: 85%;} } .gdpr_fmi a:before{ display:none; } .gdpr_w{width:100%;} .f-w-f2 { padding: 50px 0px; } footer amp-consent.amp-active { z-index:9999; display: initial; position: inherit; height:20px; width:100%; } body[class*="amp-iso-country-"] .amp-active{ display: contents; } #post-consent-ui { position: fixed; z-index: 9999; left: 45%; margin-top: 10px; top: 0; } @font-face { font-family: Poppins;font-display: optional;font-style: normal;font-weight: 400;src: local('Poppins Regular '), local('Poppins-Regular'), url(https://fonts.gstatic.com/s/poppins/v13/pxiEyp8kv8JHgFVrFJDUc1NECPY.ttf);}@font-face { font-family: Poppins;font-display: optional;font-style: normal;font-weight: 500;src: local('Poppins Medium '), local('Poppins-Medium'), url(https://fonts.gstatic.com/s/poppins/v13/pxiByp8kv8JHgFVrLGT9V1tvFP-KUEg.ttf);}@font-face { font-family: Poppins;font-display: optional;font-style: normal;font-weight: 700;src: local('Poppins Bold '), local('Poppins-Bold'), url(https://fonts.gstatic.com/s/poppins/v13/pxiByp8kv8JHgFVrLCz7V1tvFP-KUEg.ttf);}a.heateor_sss_amp{padding:0 4px}div.heateor_sss_horizontal_sharing a amp-img{display:inline-block}.heateor_sss_amp_instagram img{background-color:#624E47}.heateor_sss_amp_yummly img{background-color:#E16120}.heateor_sss_amp_youtube img{background-color:#ff0000}.heateor_sss_amp_buffer img{background-color:#000}.heateor_sss_amp_delicious img{background-color:#53BEEE}.heateor_sss_amp_facebook img{background-color:#3C589A}.heateor_sss_amp_digg img{background-color:#006094}.heateor_sss_amp_email img{background-color:#649A3F}.heateor_sss_amp_float_it img{background-color:#53BEEE}.heateor_sss_amp_linkedin img{background-color:#0077B5}.heateor_sss_amp_pinterest img{background-color:#CC2329}.heateor_sss_amp_print img{background-color:#FD6500}.heateor_sss_amp_reddit img{background-color:#FF5700}.heateor_sss_amp_stocktwits img{background-color:#40576F}.heateor_sss_amp_mewe img{background-color:#007da1}.heateor_sss_amp_mix img{background-color:#ff8226}.heateor_sss_amp_tumblr img{background-color:#29435D}.heateor_sss_amp_twitter img{background-color:#55acee}.heateor_sss_amp_vkontakte img{background-color:#5E84AC}.heateor_sss_amp_yahoo img{background-color:#8F03CC}.heateor_sss_amp_xing img{background-color:#00797D}.heateor_sss_amp_instagram img{background-color:#527FA4}.heateor_sss_amp_whatsapp img{background-color:#55EB4C}.heateor_sss_amp_aim img{background-color:#10ff00}.heateor_sss_amp_amazon_wish_list img{background-color:#ffe000}.heateor_sss_amp_aol_mail img{background-color:#2A2A2A}.heateor_sss_amp_app_net img{background-color:#5D5D5D}.heateor_sss_amp_baidu img{background-color:#2319DC}.heateor_sss_amp_balatarin img{background-color:#fff}.heateor_sss_amp_bibsonomy img{background-color:#000}.heateor_sss_amp_bitty_browser img{background-color:#EFEFEF}.heateor_sss_amp_blinklist img{background-color:#3D3C3B}.heateor_sss_amp_blogger_post img{background-color:#FDA352}.heateor_sss_amp_blogmarks img{background-color:#535353}.heateor_sss_amp_bookmarks_fr img{background-color:#E8EAD4}.heateor_sss_amp_box_net img{background-color:#1A74B0}.heateor_sss_amp_buddymarks img{background-color:#ffd400}.heateor_sss_amp_care2_news img{background-color:#6EB43F}.heateor_sss_amp_citeulike img{background-color:#2781CD}.heateor_sss_amp_comment img{background-color:#444}.heateor_sss_amp_diary_ru img{background-color:#E8D8C6}.heateor_sss_amp_diaspora img{background-color:#2E3436}.heateor_sss_amp_dihitt img{background-color:#FF6300}.heateor_sss_amp_diigo img{background-color:#4A8BCA}.heateor_sss_amp_douban img{background-color:#497700}.heateor_sss_amp_draugiem img{background-color:#ffad66}.heateor_sss_amp_dzone img{background-color:#fff088}.heateor_sss_amp_evernote img{background-color:#8BE056}.heateor_sss_amp_facebook_messenger img{background-color:#0084FF}.heateor_sss_amp_fark img{background-color:#555}.heateor_sss_amp_fintel img{background-color:#087515}.heateor_sss_amp_flipboard img{background-color:#CC0000}.heateor_sss_amp_folkd img{background-color:#0F70B2}.heateor_sss_amp_google_classroom img{background-color:#FFC112}.heateor_sss_amp_google_bookmarks img{background-color:#CB0909}.heateor_sss_amp_google_gmail img{background-color:#E5E5E5}.heateor_sss_amp_hacker_news img{background-color:#F60}.heateor_sss_amp_hatena img{background-color:#00A6DB}.heateor_sss_amp_instapaper img{background-color:#EDEDED}.heateor_sss_amp_jamespot img{background-color:#FF9E2C}.heateor_sss_amp_kakao img{background-color:#FCB700}.heateor_sss_amp_kik img{background-color:#2A2A2A}.heateor_sss_amp_kindle_it img{background-color:#2A2A2A}.heateor_sss_amp_known img{background-color:#fff101}.heateor_sss_amp_line img{background-color:#00C300}.heateor_sss_amp_livejournal img{background-color:#EDEDED}.heateor_sss_amp_mail_ru img{background-color:#356FAC}.heateor_sss_amp_mendeley img{background-color:#A70805}.heateor_sss_amp_meneame img{background-color:#FF7D12}.heateor_sss_amp_mixi img{background-color:#EDEDED}.heateor_sss_amp_myspace img{background-color:#2A2A2A}.heateor_sss_amp_netlog img{background-color:#2A2A2A}.heateor_sss_amp_netvouz img{background-color:#c0ff00}.heateor_sss_amp_newsvine img{background-color:#055D00}.heateor_sss_amp_nujij img{background-color:#D40000}.heateor_sss_amp_odnoklassniki img{background-color:#F2720C}.heateor_sss_amp_oknotizie img{background-color:#fdff88}.heateor_sss_amp_outlook_com img{background-color:#0072C6}.heateor_sss_amp_papaly img{background-color:#3AC0F6}.heateor_sss_amp_pinboard img{background-color:#1341DE}.heateor_sss_amp_plurk img{background-color:#CF682F}.heateor_sss_amp_pocket img{background-color:#f0f0f0}.heateor_sss_amp_polyvore img{background-color:#2A2A2A}.heateor_sss_amp_printfriendly img{background-color:#61D1D5}.heateor_sss_amp_protopage_bookmarks img{background-color:#413FFF}.heateor_sss_amp_pusha img{background-color:#0072B8}.heateor_sss_amp_qzone img{background-color:#2B82D9}.heateor_sss_amp_refind img{background-color:#1492ef}.heateor_sss_amp_rediff_mypage img{background-color:#D20000}.heateor_sss_amp_renren img{background-color:#005EAC}.heateor_sss_amp_segnalo img{background-color:#fdff88}.heateor_sss_amp_sina_weibo img{background-color:#ff0}.heateor_sss_amp_sitejot img{background-color:#ffc800}.heateor_sss_amp_skype img{background-color:#00AFF0}.heateor_sss_amp_sms img{background-color:#6ebe45}.heateor_sss_amp_slashdot img{background-color:#004242}.heateor_sss_amp_stumpedia img{background-color:#EDEDED}.heateor_sss_amp_svejo img{background-color:#fa7aa3}.heateor_sss_amp_symbaloo_feeds img{background-color:#6DA8F7}.heateor_sss_amp_telegram img{background-color:#3DA5f1}.heateor_sss_amp_trello img{background-color:#1189CE}.heateor_sss_amp_tuenti img{background-color:#0075C9}.heateor_sss_amp_twiddla img{background-color:#EDEDED}.heateor_sss_amp_typepad_post img{background-color:#2A2A2A}.heateor_sss_amp_viadeo img{background-color:#2A2A2A}.heateor_sss_amp_viber img{background-color:#8B628F}.heateor_sss_amp_wanelo img{background-color:#fff}.heateor_sss_amp_webnews img{background-color:#CC2512}.heateor_sss_amp_wordpress img{background-color:#464646}.heateor_sss_amp_wykop img{background-color:#367DA9}.heateor_sss_amp_yahoo_mail img{background-color:#400090}.heateor_sss_amp_yahoo_messenger img{background-color:#400090}.heateor_sss_amp_yoolink img{background-color:#A2C538}.heateor_sss_amp_youmob img{background-color:#3B599D}.heateor_sss_amp_gentlereader img{background-color:#46aecf}.heateor_sss_amp_threema img{background-color:#2A2A2A}.heateor_sss_vertical_sharing{position:fixed;left:11px;z-index:99999}.heateor-total-share-count .sss_share_count{color:#666;font-size:23px}.heateor-total-share-count .sss_share_lbl{color:#666}.amp-wp-enforced-sizes img[alt="Pinterest"]{background:#cc2329}.amp-wp-enforced-sizes img[alt="Viber"]{background:#8b628f}.amp-wp-enforced-sizes img[alt="Print"]{background:#fd6500}.amp-wp-enforced-sizes img[alt="Threema"]{background:#2a2a2a}.amp-wp-article-content .heateor_sss_vertical_sharing{left:5px}.amp-wp-article-content amp-img[alt="Pinterest"]{left:4px}.amp-wp-enforced-sizes img[alt="MySpace"]{background:#2a2a2a} amp-web-push-widget button.amp-subscribe { display: inline-flex; align-items: center; border-radius: 5px; border: 0; box-sizing: border-box; margin: 0; padding: 10px 15px; cursor: pointer; outline: none; font-size: 15px; font-weight: 500; background: #4A90E2; margin-top: 7px; color: white; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.5); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } a.heateor_sss_amp{padding:0 4px;}div.heateor_sss_horizontal_sharing a amp-img{display:inline-block;}.heateor_sss_amp_gab img{background-color:#25CC80}.heateor_sss_amp_parler img{background-color:#892E5E}.heateor_sss_amp_gettr img{background-color:#E50000}.heateor_sss_amp_instagram img{background-color:#624E47}.heateor_sss_amp_yummly img{background-color:#E16120}.heateor_sss_amp_youtube img{background-color:#ff0000}.heateor_sss_amp_teams img{background-color:#5059c9}.heateor_sss_amp_google_translate img{background-color:#528ff5}.heateor_sss_amp_x img{background-color:#2a2a2a}.heateor_sss_amp_rutube img{background-color:#14191f}.heateor_sss_amp_buffer img{background-color:#000}.heateor_sss_amp_delicious img{background-color:#53BEEE}.heateor_sss_amp_rss img{background-color:#e3702d}.heateor_sss_amp_facebook img{background-color:#0765FE}.heateor_sss_amp_perplexity img{background-color:#165962}.heateor_sss_amp_claude img{background-color:#D97757}.heateor_sss_amp_google_ai img{background-color:#000}.heateor_sss_amp_grok img{background-color:#000}.heateor_sss_amp_chatgpt img{background-color:#000}.heateor_sss_amp_digg img{background-color:#006094}.heateor_sss_amp_email img{background-color:#649A3F}.heateor_sss_amp_float_it img{background-color:#53BEEE}.heateor_sss_amp_linkedin img{background-color:#0077B5}.heateor_sss_amp_pinterest img{background-color:#CC2329}.heateor_sss_amp_print img{background-color:#FD6500}.heateor_sss_amp_reddit img{background-color:#FF5700}.heateor_sss_amp_mastodon img{background-color:#6364FF}.heateor_sss_amp_stocktwits img{background-color: #40576F}.heateor_sss_amp_mewe img{background-color:#007da1}.heateor_sss_amp_mix img{background-color:#ff8226}.heateor_sss_amp_tumblr img{background-color:#29435D}.heateor_sss_amp_twitter img{background-color:#55acee}.heateor_sss_amp_vkontakte img{background-color:#0077FF}.heateor_sss_amp_yahoo img{background-color:#8F03CC}.heateor_sss_amp_xing img{background-color:#00797D}.heateor_sss_amp_instagram img{background-color:#527FA4}.heateor_sss_amp_whatsapp img{background-color:#55EB4C}.heateor_sss_amp_aim img{background-color: #10ff00}.heateor_sss_amp_amazon_wish_list img{background-color: #ffe000}.heateor_sss_amp_aol_mail img{background-color: #2A2A2A}.heateor_sss_amp_app_net img{background-color: #5D5D5D}.heateor_sss_amp_balatarin img{background-color: #fff}.heateor_sss_amp_bibsonomy img{background-color: #000}.heateor_sss_amp_bitty_browser img{background-color: #EFEFEF}.heateor_sss_amp_blinklist img{background-color: #3D3C3B}.heateor_sss_amp_blogger_post img{background-color: #FDA352}.heateor_sss_amp_blogmarks img{background-color: #535353}.heateor_sss_amp_bookmarks_fr img{background-color: #E8EAD4}.heateor_sss_amp_box_net img{background-color: #1A74B0}.heateor_sss_amp_buddymarks img{background-color: #ffd400}.heateor_sss_amp_care2_news img{background-color: #6EB43F}.heateor_sss_amp_comment img{background-color: #444}.heateor_sss_amp_diary_ru img{background-color: #E8D8C6}.heateor_sss_amp_diaspora img{background-color: #2E3436}.heateor_sss_amp_dihitt img{background-color: #FF6300}.heateor_sss_amp_diigo img{background-color: #4A8BCA}.heateor_sss_amp_douban img{background-color: #497700}.heateor_sss_amp_draugiem img{background-color: #ffad66}.heateor_sss_amp_evernote img{background-color: #8BE056}.heateor_sss_amp_facebook_messenger img{background-color: #0084FF}.heateor_sss_amp_fark img{background-color: #555}.heateor_sss_amp_fintel img{background-color: #087515}.heateor_sss_amp_flipboard img{background-color: #CC0000}.heateor_sss_amp_folkd img{background-color: #0F70B2}.heateor_sss_amp_google_news img{background-color: #4285F4}.heateor_sss_amp_google_classroom img{background-color: #FFC112}.heateor_sss_amp_google_gmail img{background-color: #E5E5E5}.heateor_sss_amp_hacker_news img{background-color: #F60}.heateor_sss_amp_hatena img{background-color: #00A6DB}.heateor_sss_amp_instapaper img{background-color: #EDEDED}.heateor_sss_amp_jamespot img{background-color: #FF9E2C}.heateor_sss_amp_kakao img{background-color: #FCB700}.heateor_sss_amp_kik img{background-color: #2A2A2A}.heateor_sss_amp_kindle_it img{background-color: #2A2A2A}.heateor_sss_amp_known img{background-color: #fff101}.heateor_sss_amp_line img{background-color: #00C300}.heateor_sss_amp_livejournal img{background-color: #EDEDED}.heateor_sss_amp_mail_ru img{background-color: #356FAC}.heateor_sss_amp_mendeley img{background-color: #A70805}.heateor_sss_amp_meneame img{background-color: #FF7D12}.heateor_sss_amp_mixi img{background-color: #EDEDED}.heateor_sss_amp_myspace img{background-color: #2A2A2A}.heateor_sss_amp_netlog img{background-color: #2A2A2A}.heateor_sss_amp_netvouz img{background-color: #c0ff00}.heateor_sss_amp_newsvine img{background-color: #055D00}.heateor_sss_amp_nujij img{background-color: #D40000}.heateor_sss_amp_odnoklassniki img{background-color: #F2720C}.heateor_sss_amp_oknotizie img{background-color: #fdff88}.heateor_sss_amp_outlook_com img{background-color: #0072C6}.heateor_sss_amp_papaly img{background-color: #3AC0F6}.heateor_sss_amp_pinboard img{background-color: #1341DE}.heateor_sss_amp_plurk img{background-color: #CF682F}.heateor_sss_amp_pocket img{background-color: #ee4056}.heateor_sss_amp_polyvore img{background-color: #2A2A2A}.heateor_sss_amp_printfriendly img{background-color: #61D1D5}.heateor_sss_amp_protopage_bookmarks img{background-color: #413FFF}.heateor_sss_amp_pusha img{background-color: #0072B8}.heateor_sss_amp_qzone img{background-color: #2B82D9}.heateor_sss_amp_refind img{background-color: #1492ef}.heateor_sss_amp_rediff_mypage img{background-color: #D20000}.heateor_sss_amp_renren img{background-color: #005EAC}.heateor_sss_amp_segnalo img{background-color: #fdff88}.heateor_sss_amp_sina_weibo img{background-color: #ff0}.heateor_sss_amp_sitejot img{background-color: #ffc800}.heateor_sss_amp_skype img{background-color: #00AFF0}.heateor_sss_amp_sms img{background-color: #6ebe45}.heateor_sss_amp_slashdot img{background-color: #004242}.heateor_sss_amp_stumpedia img{background-color: #EDEDED}.heateor_sss_amp_svejo img{background-color: #fa7aa3}.heateor_sss_amp_symbaloo_feeds img{background-color: #6DA8F7}.heateor_sss_amp_telegram img{background-color: #3DA5f1}.heateor_sss_amp_trello img{background-color: #1189CE}.heateor_sss_amp_tuenti img{background-color: #0075C9}.heateor_sss_amp_twiddla img{background-color: #EDEDED}.heateor_sss_amp_typepad_post img{background-color: #2A2A2A}.heateor_sss_amp_viadeo img{background-color: #2A2A2A}.heateor_sss_amp_viber img{background-color: #8B628F}.heateor_sss_amp_wordpress img{background-color: #464646}.heateor_sss_amp_wykop img{background-color: #367DA9}.heateor_sss_amp_yahoo_mail img{background-color: #400090}.heateor_sss_amp_yahoo_messenger img{background-color: #400090}.heateor_sss_amp_youmob img{background-color: #3B599D}.heateor_sss_amp_gentlereader img{background-color: #46aecf}.heateor_sss_amp_threema img{background-color: #2A2A2A}.heateor_sss_amp_bluesky img{background-color:#0085ff}.heateor_sss_amp_threads img{background-color:#000}.heateor_sss_amp_raindrop img{background-color:#0b7ed0}.heateor_sss_amp_micro_blog img{background-color:#ff8800}.heateor_sss_amp amp-img{border-radius:999px;} .amp-logo amp-img{width:190px} .amp-menu input{display:none;}.amp-menu li.menu-item-has-children ul{display:none;}.amp-menu li{position:relative;display:block;}.amp-menu > li a{display:block;} /* Inline styles */ div.acss138d7{clear:both;}div.acssf5b84{--relposth-columns:3;--relposth-columns_m:2;--relposth-columns_t:2;}div.acssae964{aspect-ratio:1/1;background:transparent no-repeat scroll 0% 0%;height:150px;max-width:150px;}div.acss6bdea{color:#333333;font-family:Arial;font-size:12px;height:75px;}div.acsse3e3c{font-weight:bold;}amp-img.acss334b9{max-width:35px;} .icon-widgets:before {content: "\e1bd";}.icon-search:before {content: "\e8b6";}.icon-shopping-cart:after {content: "\e8cc";}
JS

Как создать сайт с безсерверной CMS на Vue.js

От автора: сегодня мы поговорим о создании с помощью Vue js CMS. Vue.js – это прогрессивный фреймворк для создания UI, набирающий популярность среди разработчиков. Но зачем нам еще один JS фреймворк? Vue написан на опыте Angular и React, многие считают, что он проще в реализации и понимании.

Введение

Vue.js мало весит и легко принимается. Он реактивный и состоит из компонентов, что позволяет создавать подключаемые компоненты, которые можно добавлять в любой проект. Что важнее для этого урока, Vue со своей отличительной и постепенной адаптируемостью можно использовать, не подвергая риску существующий код.

Vue превосходно работает с безсерверными архитектурами приложений. Множество разработчиков сейчас предпочитают безсерверную архитектуру, так как она позволяет эффективно создавать и точно настраивать продукты, не обременяя себя (обслуживание серверов, сбои и узкие места) традиционной серверной архитектурой. Sarah Drasner недавно написала целую серию о том, как создать безсерверную корзину на Vue – хороший пример на практике.

В этом уроке вы узнаете, как создавать маркетинговые сайты в виде безсерверного приложения Vue.js с помощью ButterCMS. ButterCMS – это обезглавленная CMS и блог-платформа, позволяющая создавать приложения под управлением CMS, используя при этом любой язык программирования, в том числе и Vue. Есть и другие варианты для работы с обезглавленными CMS, но так как я раньше писал для ButterCMS и хорошо ее знаю, поэтому ее мы и будем использовать в примерах.

В этом уроке вы узнаете, как добавить производительные API контента в приложение Vue.js. По этим API легко перемещаться даже членам команды с нетехническим складом ума, что позволяет получать удовольствие от гибкого управления контентом и не развертывать/поддерживать собственную CMS.

В частности, мы разберем примеры кода для трех типов контента, встречающегося на маркетинговых сайтах: отзывы покупателей, часто задаваемые вопросы и посты в блоге.

Обратите внимание на то, что скриншоты в статье будут отличаться от ваших, на них будем минимум CSS для демонстрации. В вашем настоящем дизайне будут использоваться глобальные стили приложения, которые будут придавать страницам единообразие.

Начало работы

В качестве CMS мы будем использовать ButterCMS. Так давайте же установим ее:

npm install buttercms--save

После установки можно перейти к примерам.

Пример 1: отзывы покупателей

Давайте сделаем так, чтобы любой человек без технического склада ума в вашей команде мог добавить отзывы покупателей на сайт. Для этого мы создадим страницу, на которой будут храниться все опубликованные отзывы, рекламирующие продукт или услугу, которую мы продаем. При нажатии будет открываться страница отзыва.

Шаг 1: настройка типа страницы отзыва покупателя

В панели управления ButterCMS можно создать «тип страниц» с заголовком «Customer Case Study» и определить поля контента. После этого можно создавать первую страницу. Укажите название и URL страницы с помощью панели управления ButterCMS и заполните поля контента тем, что мы только что определили.

После всего ButterCMS API вернет вам определенную страницу в JSON формате. Это будет выглядеть примерно так:

{
  "data":{
    "slug":"acme-co",
    "fields":{
      "facebook_open_graph_title":"Acme Co loves ButterCMS",
      "seo_title":"Acme Co Customer Case Study",
      "headline":"Acme Co saved 200% on Anvil costs with ButterCMS",
      "testimonial":"<p>We've been able to make anvils faster than ever before! - <em>Chief Anvil Maker</em></p>rn<p><img src="https://webformyself.com/https://cdn.buttercms.com/NiA3IIP3Ssurz5eNJ15a" alt="Создание безсерверной CMS под управлением Vue.js" caption="false" width="249" height="249" /></p>",
      "customer_logo":"https://cdn.buttercms.com/c8oSTGcwQDC5I58km5WV",
    }
  }
}

Шаг 2: интеграция с приложением

Откройте редактор кода и создайте файл buttercms.js в папке /src. Если у вас еще нет проекта, создайте его, введя следующие команды:

vue init webpack buttercms-project
cd buttercms-project
npmi
npmi-Sbuttercms
npm run dev

Затем в файле src/buttercms.js:

import Butter from'buttercms';
constbutter=Butter('your_api_token');

Обновите роуты в приложении. Сделать это можно в router/index.js:

import Vue from'vue';
import Router from'vue-router';
import CustomersHome from'@/components/CustomersHome';
import CustomerPage from'@/components/CustomerPage';
Vue.use(Router)
exportdefaultnewRouter({
  mode:'history',
  routes:[
    {
      path:'/customers/',
      name:'customers-home',
      component:CustomersHome
    },
    {
      path:'/customers/:slug',
      name:'customer-page',
      component:CustomerPage
    }
  ]
})

Отлично, у вас есть контента в файле данных. Теперь вам нужна страница, которая будет использовать этот контент. Необходимо определить метод getpages(), который будет получать все страницы отзывов, чтобы вы могли отрендерить их все на одной лендинг пейдж (чтобы у них у всех был индекс). Это будет домашняя страница для всех опубликованных отзывов.

В файле components/CustomersHome.vue добавьте:

<script>
  // import ButterCMS from
  import{butter}from'@/buttercms'
  exportdefault{
    name:'customers-home',
    data(){
      return{
        page_title:'Customers',
        // Create array to hold the pages from ButterCMS API
        pages:[]
      }
    },
    methods:{
      // Get List of Customer Pages
      getPages(){
        butter.page.list('customer_case_study')
          .then((res)=>{
            // console.log(res.data.data) // Check the results in the console
            this.pages=res.data.data
          })
      }
    },
    created(){
      // Fire on page creation
      this.getPages()
    }
  }
</script>

… чтобы отобразить результаты по одному:

<template>
  <div id="customers-home">
    <h1>{{page_title}}</h1>
    <div v-for="(page,index) in pages":key="page.slug + '_' + index">
      <router-link:to="'/customers/' + page.slug">
        <div>
          <img:src="page.fields.customer_logo"alt="">
          <h2>{{page.fields.headline}}</h2>
        </div>
      </router-link>
    </div>
  </div>
</template>

Ниже показан пример того, что должно получиться после публикации одного отзыва:

Теперь необходимо создать страницу, на которую мы будем переходить по клику на отзыв с домашней страницы. Для этого определите метод getPage() в файле components/CustomerPage.vue, чтобы получить конкретную страницу покупателя по ее уникальному идентификатору:

&lt;script>
  import{butter}from'@/buttercms'
  exportdefault{
    name:'customer-page',
    data(){
      return{
        slug:this.$route.params.slug,
        page:{
          slug:'',
          fields:{}
        }
      }
    },
    methods:{
      getPage(){
        butter.page.retrieve('customer_case_study',this.slug)
          .then((res)=>{
            console.log(res.data.data)
            this.page=res.data.data
          }).catch((res)=>{
            console.log(res)
          })
      }
    },
    created(){
      this.getPage()
    }
  }
&lt;/script>

Как и с домашней страницей и отзывами, необходимо показать контент, задав шаблон и вызвав нужные поля контента:

<template>
  <div id="customer-page">
    <figure>
      <img:src="page.fields.customer_logo">
    </figure>
    <h1>{{page.fields.headline}}</h1>
    <h3>Testimonials</h3>
    <div v-html="page.fields.testimonial"></div>
    <div v-html="page.fields.body"></div>
  </div>
</template>

Отлично! Теперь вы можете переходить прямо на страницу со всеми опубликованными отзывами, а по клику на любой отзыв вы переходите на детальную страницу.


Пример 2: часто задаваемые вопросы

Давайте посмотрим, как создать страницу часто задаваемых вопросов (FAQ) для приложения. Для этого будем использовать ButterCMS «Content Fields». Content fields – это просто глобальные части контента, которыми может управлять команда. Этот контент может распространяться на несколько страниц, а у каждого content field (поля контента) есть свой уникальный ID для запроса (это вы увидите ниже).

Шаг 1: настройка полей контента

Сперва, необходимо настроить несколько пользовательских полей контента. С помощью панели управления можно настроить рабочую область для организации полей контента. Рабочие области позволяют редакторам контента работать с ним, не затрагивая разработку или API.

В рабочей области кликните на кнопку, чтобы создать новое поле контента. Выберите тип Object, в качестве названия поля укажите FAQ Headline. Поле получит свой API идентификатор — faq_headline.

После сохранения добавьте еще одно поле, но в этот раз выберите тип Collection и название поля FAQ Items. Это поле получит API id — faq_items. На следующем экране создайте 2 свойства для элементов в коллекции и вернитесь в рабочую область, чтобы обновить заголовки и добавить посты в FAQ.

Шаг 2: интеграция с приложением

После создания динамического контента на основе полей контента необходимо его отобразить в приложении. Для этого необходимо получить поля с помощью запроса к API и передать их в представление. Сперва, настройте роут на страницу FAQ:

Добавим роуты FAQ в файл router/index.js:

import Vue from'vue';
import Router from'vue-router';
import FAQ from'@/components/FAQ';
Vue.use(Router);
exportdefaultnewRouter({
  mode:'history',
  routes:[
    {
      path:'/faq',
      name:'faq',
      component:FAQ
    }
  ]
})

Создайте components/FAQ.vue с запросом на получение FAQ контента из API:

<script>
  import{butter}from'@/buttercms'
  exportdefault{
    name:'faq',
    data(){
      return{
        page_title:'FAQ',
        faq_items:[]
      }
    },
    methods:{
      getFaqs(){
        butter.content.retrieve(['faq_headline','faq_items'])
          .then((res)=>{
            console.log(res.data.data)
            this.page_title=res.data.data.faq_headline
            this.faq_items=res.data.data.faq_items
          })
      }
    },
    created(){
      this.getFaqs()
    }
  }
</script>

Обратите внимание, что мы заранее указали page_title как FAQ и обновили его с помощью API запроса к полям контента FAQ.

Создайте <template>:

<template>
  <div id="faq">
    <h1>{{page_title}}</h1>
    <div v-for="(faq, index) in faq_items":key="index">
      <p>{{faq.question}}</p>
      <p>{{faq.answer}}</p>
    </div>
  </div>
</template>

Результат должен быть примерно такой:

Теперь любой человек из вашей команды может обновить значения через панель управления ButterCMS, и соответствующий контент в приложении обновится автоматически.


Пример 3: посты в блоге

Разберем механизм блога для приложения.

Шаг 1: отображение постов

Начну с создания роута блога с помощью vue-router. Для отображения постов необходимо создать простой роут /blog и получать посты блога, а также роут /blog/:slug для обработки отдельных постов.

Файл router/index.js:

import Vue from 'vue';
import Router from 'vue-router';
import BlogHome from '@/components/BlogHome';
import BlogPost from'@/components/BlogPost';
Vue.use(Router)
exportdefaultnewRouter({
  mode:'history',
  routes:[
    {
      path:'/blog/',
      name:'blog-home',
      component:BlogHome
    },
    {
      path:'/blog/:slug',
      name:'blog-post',
      component:BlogPost
    }
  ]
})

Шаг 2: создание домашней страницы блога

Чтобы создать домашнюю страницу блога, на которой будут отображаться последние опубликованные посты, необходимо создать Vue компонент для домашней страницы блога в файле components/BlogHome.vue:

<script>
  import{butter}from'@/buttercms'
  exportdefault{
    name:'blog-home',
    data(){
      return{
        page_title:'Blog',
        posts:[]
      }
    },
    methods:{
      getPosts(){
        butter.post.list({
          page:1,
          page_size:10
        }).then((res)=>{
          // console.log(res.data)
          this.posts=res.data.data
        })
      }
    },
    created(){
      this.getPosts()
    }
  }
</script>

Если вы разобрали предыдущие примеры, то могли заметить здесь шаблон и понять, что для отображения контента необходимо определить шаблон и вызвать поля в том же файле компонента:

<template>
  <div id="blog-home">
      <h1>{{page_title}}</h1>
      <div v-for="(post,index) in posts":key="post.slug + '_' + index">
        <router-link:to="'/blog/' + post.slug">
          <article class="media">
            <figure>
              <img v-if="post.featured_image":src="post.featured_image"alt="">
              <img v-elsesrc="http://via.placeholder.com/250x250"alt="">
            </figure>
            <h2>{{post.title}}</h2>
            <p>{{post.summary}}</p>
          </article>
        </router-link>
      </div>
  </div>
</template>

Если ваши поля совпадают с примером, то домашняя страница блога должна быть примерно такой:

Шаг 3: создание поста в блоге

Далее создайте файл components/BlogPost.vue – это будет представление для одного поста:

<script>
  import{butter}from'@/buttercms'
  exportdefault{
    name:'blog-post',
    data(){
      return{
        post:{}
      }
    },
    methods:{
      getPost(){
        butter.post.retrieve(this.$route.params.slug)
          .then((res)=>{
            // console.log(res.data)
            this.post=res.data
          }).catch((res)=>{
            console.log(res)
          })
      }
    },
    created(){
      this.getPost()
    }
  }
</script>

Вы могли догадаться, но здесь необходимо определить шаблон и послать запрос на поля контента поста в блоге:

&lt;template>
  &lt;div id="blog-post">
    &lt;h1>{{post.data.title}}&lt;/h1>
    &lt;h4>{{post.data.author.first_name}}{{post.data.author.last_name}}&lt;/h4>
    &lt;div v-html="post.data.body">&lt;/div>
    &lt;router-link v-if="post.meta.previous_post":to="/blog/ + post.meta.previous_post.slug"class="button">
      {{post.meta.previous_post.title}}
    &lt;/router-link>
    &lt;router-link v-if="post.meta.next_post":to="/blog/ + post.meta.next_post.slug"class="button">
      {{post.meta.next_post.title}}
    &lt;/router-link>
  &lt;/div>
&lt;/template>

Если ваши поля совпадают с примером, то получиться должно примерно следующее:

Шаг 4: обработка роутов постов блога

На данном этапе ваше приложение получает все посты блога, что позволяет перейти к отдельным постам. Но вы заметили, что кнопки назад/вперед в браузере не работают? Почему? Если роут используется с params, то будет задействован тот же объект компонента, когда пользователь перейдет с /blog/foo на /blog/bar.

Такой способ эффективнее уничтожения старого объекта и создания нового, так как оба роута рендерят один компонент. Но это так же значит, что не вызываются хуки жизненного цикла компонента.

Это можно починить. Необходимо следить за объектом $route и вызывать getPost(), когда роут изменяется. Для этого обновите раздел script в файле components/BlogPost.vue:

<script>
  import{butter}from'@/buttercms';
  exportdefault{
    name:'blog-post',
    data(){
      return{
        post:{}
      }
    },
    methods:{
      getPost(){
        butter.post.retrieve(this.$route.params.slug)
          .then((res)=>{
            // console.log(res.data)
            this.post=res.data
          }).catch((res)=>{
            console.log(res)
          })
      }
    },
    watch:{
      $route(to,from){
        this.getPost()
      }
    },
    created(){
      this.getPost()
    }
  }
</script>

Сейчас в вашем приложении есть рабочий блог, который легко можно обновлять через панель управления CMS.

Также с помощью API можно применять фильтры и использовать избранный контент в блоге на категориях, тегах и авторах. С точки зрения управления различными аспектами блога (RSS, Atom feeds, карта сайта и стилизация контента через CSS) можно много чего сделать через API.

Заключение

Поздравляю! Вы создали безсерверное приложение Vue.js с производительным API контента. Теперь вы имеете реальные примеры использования контента, который можно встретить на любом маркетинговом сайте. Ваши разработчики могут вернуться к программированию, а не технари получили легкий способ управления контентом без необходимости лезть в код. Что еще лучше, приложение работает с динамическим контентом, который может адаптироваться, переназначаться и масштабироваться под будущие нужды.

Автор: Jake Lumetta

Источник: https://css-tricks.com/

Редакция: Команда webformyself.

Поделится
Admin

Recent Posts