मैंने ओपी पूछ रहा था कि काफी कुछ करने के लिए कुछ समय पहले इस सवाल और दूसरों को देखा। दुर्भाग्यवश, वू पर अधिकांश जानकारी एक एसपीए संदर्भ में दी गई है। हालांकि, जैसा कि इवान आपने अक्सर दोहराया है, वू की राय नहीं है और एसपीए के भीतर उपयोग की आवश्यकता नहीं है।
मैं अपने कुछ निष्कर्षों को साझा करना चाहता हूं और Django और Vue को एक साथ काम करने के लिए एक संभावित दृष्टिकोण को स्केच करना चाहता हूं। जबकि एक एसपीए की आवश्यकता नहीं है मुझे लगता है कि वू की वास्तविक शक्ति इसके घटकों से आती है और उस तरह से आपको वेबपैक या इसी तरह के दृष्टिकोण की ओर धक्का देता है, एचटीएमएल में सरल स्टैंडअलोन मोड नहीं है।
इसके अलावा, बस स्पष्ट होने के लिए: मेरी सामग्री का 9 0% + Django कोड और टेम्पलेट्स पहले जैसा ही बना हुआ था। Django विशेष रूप से परवाह नहीं है कि यह webpack_loader और render_bundle का उपयोग कर रहा है। और भी कम है कि render_bundle Vue के साथ कुछ करने के लिए है। Django template blocks
, verbatim
टैग और वू slots
के बीच, आपको बहुत लचीलापन मिलता है जो आपको अपनी अधिकांश मौजूदा सामग्री को अकेले छोड़ने की अनुमति देता है।
अन्त में, Django-webpack की मेरी समझ है कि, जब आप तैयार हैं, आप कर सकते हैं collectstatic
और अपने सभी webpack-उत्पन्न बंडलों तो किसी भी नोड के बिना, Django/nginx/अपाचे, अन्य निश्चित संसाधनों की तरह से परोसा जा सकता है या webpack। इस तरह आप जटिल उत्पादन जेएस को अपने उत्पादन प्रणालियों में नहीं जोड़ रहे हैं। :
क्षमा याचना, यह काफी अधूरा है, के रूप में मैं इतना बाहर अलग करना रहा हूँ काम कर कोड की उम्मीद नहीं है (ध्यान दें यह पिछले एक धारणा है, इस बात की पुष्टि या टिप्पणी में खंडन करता है, तो आप जानते हैं कि कृपया है)। लेकिन उम्मीद है कि यह आपको एक विचार देगा।
mysite/__ full12_vue.html:
यह मेरा आधार Vue-ify Django टेम्पलेट है कि मेरे मौजूदा Django आधार टेम्पलेट फैली हुई है, __full12.html है।
मान लेते हैं कि __full12.html सभी सामान्य Django ब्लॉक, को परिभाषित करता है की तरह {% ब्लॉक सामग्री%} और तरह
(वास्तव में, वहाँ ID bme-vue
साथ एक बहुत ही महत्वपूर्ण div है मैं इतना हमने इस टेम्पलेट को अंत में भी जोड़ा है।)
मैंने उपयोगकर्ता संदेशों को प्रदर्शित करने के लिए एक व्यू घटक जोड़ा है।
और वू + बूटस्ट्रैप ड्रॉपडाउन का उपयोग करने के लिए मेनू टेम्पलेट को फिर से परिभाषित किया गया।
{% extends "mysite/__full12.html" %}
<!-- KEY: use this to hook up to https://github.com/ezhome/django-webpack-loader -->
{% load render_bundle from webpack_loader %}
{% block nav %}
<!-- uses Vue to setup Bootstrap dropdown menus -->
{% include "mysite/menu_vue.html" %}
{% endblock nav %}
{% block user_msg %}
<div class="row">
<div class="col-6">
<!-- uses Vue to display user messages -->
<bme-user-messages>
<div>THIS SHOULDNT APPEAR ON SCREEN IF VUE WORKED</div>
</bme-user-messages>
</div>
</div>
{% endblock user_msg %}
{%block extra_js_body_end%}
<!-- KEY this points Django Webpack loader to appropriate Webpack entry point -->
{% render_bundle bundle_name %}
{%endblock extra_js_body_end%}
webpack.config.development.js:
यह वह जगह है जहाँ आप Webpack जो जे एस BUNDLE_NAME आप ध्यान में रखते हुए यह निर्दिष्ट करने के लिए सेवा करने के लिए बताओ।
वेबपैक को कॉन्फ़िगर कैसे करें मेरी पोस्ट के दायरे से बाहर है, लेकिन मैं आपको आश्वस्त कर सकता हूं कि यह वास्तविक पीआईए था। मैंने पाइप django-webpack-loader, फिर https://github.com/NdagiStanley/vue-django के बाद बूटस्ट्रैप 4 सामान के साथ शुरू किया। हालांकि, अंतिम परिणाम स्टैंडअलोन की तुलना में अधिक शक्तिशाली है, मेरी राय में।
/*
webpack config dev for retest
*/
config.entry = {
"main" : [
'webpack-dev-server/client?http://localhost:3000','../../static_src/js/index'],
// ....stuff..
//KEY: ONE entrypoint for EACH bundlename that you use.
"mydjangoappname/some_django_view" : ["../../static_src/js/mydjangoappname/some_django_view"],
"mydjangoappname/another_django_view" : ["../../static_src/js/mydjangoappname/another_django_view"],
// ....stuff..
}
// ....stuff left out...
mydjangoappname/some_django_template.html
अंत में, हम कुछ वास्तविक सामग्री प्रदर्शित करने के लिए तैयार हैं:
bme-nav-item
और bme-tab-pane
2 कस्टम व्यू घटकों मैं बूटस्ट्रैप 4 टैब एनएवी और सामग्री के लिए उपयोग कर रहे हैं ।
Django var settings= some-json-object
बल्कि पेज-सामान्य की तुलना में उदाहरण के विशेष संवाद करने के लिए, Vue और जे एस के लिए डेटा का उपयोग करता
{% extends "mysite/__full12_vue.html" %}
<script>
// KEY: settings is provided by json.dumps(some_settings_dictionary)
// which your views puts into your RequestContext.
// this is how Django tells Vue what changes with different data, on the same view
var settings = {{settings | safe}};
</script>
{% block content %}
<!-- a button to run a Celery batch via a post command, url should probably come
from Django url reverse and be put into a Vue property...
-->
<button v-bind:data-url="url_batch" type="button" class="btn btn-block btn-outline-primary" @click.prevent="run_batch">
<!-- lotsa stuff left out.... -->
<ul id="tab-contents-nav" class="nav nav-tabs nav-pills">
<!-- *label* is using a Vue Prop and because there is no {% verbatim %} guard around it, Django will
inject the contents. {% urlrev xxx %} could be used to write to an 'url' prop. Ditto the conditional
inclusion, by Django, of a template if it's in the RequestContext.
-->
{% if templatename_details %}
<bme-nav-item link="details"
label="{{details_label}}" >
</bme-nav-item>
{% endif %}
<!-- lotsa stuff left out.... -->
<bme-tab-pane link="details">
<div slot="content">
<!-- KEY: Vue slots are incredibly powerful with Django. Basically this is saying
to Django : inject what you want in the slot, using your include, I'll tidy up afterwards.
In my case, this is a Bootstrap NavItem + NavTab
-->
{% if templatename_details %}
{% include templatename_details %}
{% else %}
<span class="text-warning">SHOULDNT APPEAR IF VUE WORKED </span>
{% endif %}
</div>
</bme-tab-pane>
{% endblock content %}
mydjangoappname/some_django_view.js:
import Vue from 'vue';
import Vuex from 'vuex';
//now Vue is using Vuex, which injects $store centralized state variables as needed
Vue.use(Vuex);
//KEY: re-using components defined once.
import {base_messages, base_components} from '../mysite/commonbase.js';
var local_components = {
//nothing, but I could have imported some other components to mix-n-match
//in any case, bme-nav-item, bme-tab-pane and bme-user-messages need to
//coming from somewhere for this page!
};
const components = Object.assign({}, base_components, local_components);
//we're going to put together a Vue on the fly...
export function dovue(config) {
//KEY: The store is a Vuex object - don't be fooled, it's not SPA-only
// it's the easiest way to coherently share data across Vue Components, so use it.
store.commit('initialize', config);
//here I am telling the store which html IDs need hiding
var li_tohide = settings.li_tohide || [];
li_tohide.forEach(function(hidden) {
store.commit('add_hidden', hidden);
});
/* eslint-disable no-new */
var vm = new Vue({
//KEY: This tells the Vue instance what parts of your html are in its scope.
el: '#bme-vue'
//KEY: each bme-xxx and bme-yyy special tag needs to be found in components below
//otherwise you'll see my SHOULDNT APPEAR IF VUE WORKED text in your page
,components: components
,data: {
li_rowcount: window.settings.li_rowcount || []
,csrf_token: window.csrf_token
,url_batch: "some url"
}
,mounted: function() {
// a Vue lifecycle hook. You could use to set up Vue Event listening for example
console.log("data.js.lifecycle.mounted");
}
,methods : {
,run_batch: function(e) {
//hook this up to a button
console.assert(this.$data, COMPONENTNAME + ".run_batch.this.$data missing. check object types");
var url = e.target.dataset.url
//this is defined elsewhere
post_url_message(this, url, this.csrf_token);
}
}
//the Vuex instance to use for this Vue.
,store: store
});
//did Django provide any user messages that need displaying?
var li_user_message = config.li_user_message || [];
li_user_message.forEach(function(user_message, i) {
//the bme-user-messages Component? It's listening for this event
//and will display Bootstrap Alerts for them.
vm.$emit(base_messages.EV_USER_MESSAGE, user_message);
});
return vm;
}
//various app and page specific settings...
import {app_config, LOCALNAV_LINK, TOPNAV_LINK_OTHERS} from "./constants";
var page_config = {
//used to show which navigation items are .active
localnav_link : LOCALNAV_LINK.data
, topnav_link: TOPNAV_LINK_OTHERS.system_edit_currentdb
};
//this is coming from Django's RequestContext.
var generated_config = window.settings;
//ok, now we are merging together a Django app level config, the page config and finally
//what the Django view has put into settings. This will be passed to the Vuex store
//individual Vue Components will then grab what they need from their $store attribute
//which will point to that Vuex instance.
var local_config = Object.assign({}, app_config, page_config, generated_config);
var vm = dovue(local_config);
vuex/सामान्य .js:
और एक बेवकूफ, ज्यादातर पढ़ने-योग्य स्टोर ई कार्यान्वयन:
//you can add your page's extra state, but this is a shared baseline
//for the site
const state = {
active_tab: ""
,topnav_link: ""
,localnav_link: ""
,li_user_message: []
,s_visible_tabid: new Set()
,urls: {}
};
const mutations = {
//this is what your page-specific JS is putting into the state.
initialize(state, config){
//initialize the store to a given configuration
//KEY: attributes that did not exist on the state in the first place wont be reactive.
// console.log("store.initialize");
Object.assign(state, config);
},
//a sample mutation
set_active_tab(state, tabid){
//which bme-tab-nav is active?
if (! state.s_visible_tab.has(tabid)){
return;
}
state.active_tab = tabid;
},
};
export {state as generic_state, mutations};
और आप सामान्य फ़ाइल पदानुक्रम की एक विचार देने के लिए:
.
./manage.py
./package.json //keep this under version control
./
├── mydjangoappname
│ ├── migrations
│ └── static
│ └── mydjangoappname
├── node_modules
├ //lots of JavaScript packages here, deposited/managed via npm && package.json
├── static
│ └── js
├── static_src
│ ├── assets
│ ├── bundles
│ │ // this is where django-webpack-loader's default config deposits generated bundles...
│ │ // probably belonged somewhere else than under static_src ...
│ │ ├── mydjangoappname
│ ├── components
│ │ ├── mydjangoappname
│ ├── css
│ ├── js
│ │ ├── mydjangoappname
│ │ └── mysite
│ └── vuex
│ ├── mydjangoappname
├── staticfiles
│ // for Production, collectstatic should grab django-webpack-loader's bundles, I think...
├── templates
│ ├── admin
│ │ └── pssystem
│ ├── mydjangoappname
│ └── mysite
└── mysite
├── config
├ // where you configure webpack and the entry points.
├ webpack.config.development.js
├── sql
│ └── sysdata
├── static
│ └── mysite
└── templatetags
ठीक है, मुझे यकीन है कि div # BME-Vue है बनाने के लिए साइट की मूल टेम्पलेट को संशोधित करने की क्या ज़रूरत थी हमेशा उपलब्ध।
शायद इस और mysite/__ full12_vue.html के बीच आवश्यक कुछ रिफैक्टरिंग की आवश्यकता है।
mysite/__ full12.html:
पहले दृष्टिकोण अलग Django और Vue क्षुधा बनाने जा रहा है:
<!-- lots of stuff left out -->
<body>
<!-- KEY: the #bme-vue wrapper/css selector tells Vue what's in scope.
it needs to span as much of the <body> as possible, but
also end right BEFORE the render_bundle tag. I set that css
selector in mydjangoappname/some_django_view.js and I'd want to
use the same selector everywhere throughout my app.
-->
<div id="bme-vue">
<!-- anything that ends up here
, including through multiple nested/overridden Django content blocks
, can be processed by Vue
, but only when have Vue-relevant markup
such as custom component tags or v-for directives.
-->
...more blocks...
{% block search %}
{% endblock search %}
<div id="main" role="main">
<div> <!-- class="container"> -->
{% block content %}
{% endblock %}
</div>
</div>
...more blocks...
</div> <!-- bme-vue -->
{%block extra_js_body_end%}
{%endblock extra_js_body_end%}
</body>
</html>
उल्लेख करना भूल गए - आपका हेडर और पाद लेख वू घटक होगा, जिसमें लेआउट और मार्कअप को परिभाषित करने वाले टेम्पलेट्स होंगे। याद रखें: सभी प्रतिपादन क्लाइंट साइड पर हैं, इसलिए पेज इंडेक्सिंग के लिए Google खोज रोबोट के लिए अनिवार्य रूप से अदृश्य होगा। – Mani