python flask jinja2使用Vue,并解决jinja2和vue冲突

本文展示了如何在Vue.js应用中利用Axios库进行HTTP请求,从Flask后端获取数据。通过修改模板变量以避免与Vue.js的默认绑定冲突,实现了数据的动态加载和展示。同时,还提供了备选方案,使用jQuery的getJSON方法达到相同效果。

http://www.axios-js.com/zh-cn/docs/
axios官网

方法1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>
<body>
    <div id="app">
        <select >
            <option v-for="item in selects" :value="item">[[item]]</option>
        </select>
        <h2>{{item}}</h2>
        <div v-for="udata in userData">
            [[ udata.name ]]
            </div>
    </div>
    <script>
        const vue = new Vue({
            el:"#app",
            delimiters: ["[[", "]]"],
            data:{
                selects:['enu','cha'],
                userData:[]
            },
            created: function() {
                var self = this
                axios.get('/api/tasks')
                .then(function (response) {
                    self.userData = (response.data);
                })
                .catch(function (error) {
                    console.log(error);
                });
            // $.getJSON('/api/tasks', function(data) {
            //     console.log(data);
            //     self.userData = data;
            //     console.log(self.userData);
                
            // })
        }
        })
        </script>
</body>

</html>

WanmaitFlask这种方式是直接disable掉jinjia2的

from flask import Flask
from flask import render_template
from flask import jsonify

class WanmaitFlask(Flask):
    jinja_options = Flask.jinja_options.copy()
    jinja_options.update(dict(variable_start_string='%%',
                              # Default is '{{', I'm changing this because Vue.js uses '{{' / '}}'
                              variable_end_string='%%',))
app=WanmaitFlask(__name__)


@app.route("/test")
def test():
    return render_template("test.html",item=[123,345])

@app.route("/api/tasks")
def tasks():
    lists=[{"name":"123"},{"name":"123"},{"name":"123"},{"name":"123"}]
    return jsonify(lists)

if __name__ == '__main__':
    app.run("0.0.0.0",8888,debug=True)

https://www.jb51.net/zt/jquerydown.htm
这是js 路径

方法2 更改vue的数据绑定方式

from flask import Flask
from flask import render_template
from flask import jsonify

# class WanmaitFlask(Flask):
#     jinja_options = Flask.jinja_options.copy()
#     jinja_options.update(dict(variable_start_string='%%',
#                               # Default is '{{', I'm changing this because Vue.js uses '{{' / '}}'
#                               variable_end_string='%%',))
app=Flask(__name__)


@app.route("/test")
def test():
    return render_template("test.html",item=[123,345])




@app.route("/api/tasks")
def tasks():
    lists=[{"name":"123"},{"name":"123"},{"name":"123"},{"name":"123"}]
    return jsonify(lists)

if __name__ == '__main__':
    app.run("0.0.0.0",8888,debug=True)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>
<body>
    <div id="app">
        <select >
            <option v-for="item in selects" :value="item">[[item]]</option>
        </select>
        <h2>{{item}}</h2>
        <div v-for="udata in userData">
            [[ udata.name ]]
            </div>
    </div>
    <script>
        const vue = new Vue({
            el:"#app",
            delimiters: ["[[", "]]"],
            data:{
                selects:['enu','cha'],
                userData:[]
            },
            created: function() {
                var self = this
                axios.get('/api/tasks')
                .then(function (response) {
                    self.userData = (response.data);
                })
                .catch(function (error) {
                    console.log(error);
                });
            // $.getJSON('/api/tasks', function(data) {
            //     console.log(data);
            //     self.userData = data;
            //     console.log(self.userData);
                
            // })
        }
        })
        </script>
</body>

</html>

****delimiters: ["[[", “]]”],这句话是很重要的,就是把{undefined{}}改成[[]]

<think> 我们正在处理的问题:在PyCharm中开发Flask项目时,使用Vue作为前端,但Vue的模板语法(如`{{ }}`)与Jinja2的模板语法冲突,因为两者都使用双花括号。 根据引用[2]引用[4],Flask默认使用Jinja2作为模板引擎,而Vue.js使用类似的语法(双花括号)进行数据绑定,这会导致在渲染模板时冲突解决方案通常有两种: 1. 修改Vue.js的模板语法分隔符,避免与Jinja2冲突2.Vue.js完全放在前端,即使用独立的静态文件,避免Jinja2去解析Vue的模板。 下面详细说明: 方法一:修改Vue.js的分隔符 在Vue实例中,可以自定义模板分隔符。例如,将`{{ }}`改为`[[ ]]`。 在创建Vue实例时,添加以下配置: ```javascript new Vue({ delimiters: ['[[', ']]'], // 其他配置... }) ``` 这样,Vue就会使用`[[ ... ]]`作为插值表达式,而Jinja2仍然使用`{{ ... }}`,从而避免冲突。 方法二:使用Vue的完整版(runtime+compiler)在前端独立构建 另一种方法是将Vue完全作为前端框架,不依赖Jinja2模板。通常,我们会在Flask中设置一个静态文件夹(static)来存放所有前端资源(包括Vue的代码),然后通过模板引入这些静态文件。 在Flask中,模板文件(Jinja2)负责生成HTML结构,而Vue负责处理前端的动态交互。这样,Jinja2只负责第一次渲染,之后由Vue接管。 具体步骤: 1.Flask项目结构中,将前端资源(如Vuejs文件、CSS文件等)放在`static`目录下。 2. 在模板文件中,通过`url_for('static', filename='path/to/vue.js')`引入Vue。 3. 在模板中,为Vue定义挂载点(使用id或class),使用Vue的语法(双花括号)时,确保这些内容不会被Jinja2渲染。可以通过将Vue相关的代码放在`{% raw %}``{% endraw %}`标签中,或者将Vue的代码放在外部的.js文件中(推荐)。 例如,在Jinja2模板中: ```html <!DOCTYPE html> <html> <head> <title>My App</title> <script src="{{ url_for('static', filename='js/vue.js') }}"></script> </head> <body> <div id="app"> <!-- 使用raw标签避免Jinja2解析Vue的语法 --> {% raw %} {{ message }} <!-- 这里Vue会解析 --> {% endraw %} </div> <script> new Vue({ el: '#app', data: { message: 'Hello Vue!' } }); </script> </body> </html> ``` 但是,更好的做法是将Vue的代码放在外部js文件中,这样就不需要在模板中使用raw标签。例如: 在模板中: ```html <div id="app"> <!-- 这里Vue会解析,但Jinja2不会处理,因为我们不在双花括号内写Jinja2变量 --> <!-- 注意:如果这里需要同时使用Jinja2变量,那么需要将Vue的数据通过其他方式传入(例如在挂载点设置data-*属性) --> {{ message }} <!-- 这里Vue解析,但注意Jinja2也会尝试解析,所以如果message是Jinja2变量就会冲突 --> </div> <!-- 引入外部js --> <script src="{{ url_for('static', filename='js/app.js') }}"></script> ``` 在app.js中: ```javascript new Vue({ el: '#app', data: { message: 'Hello Vue!' } }); ``` 但是,如果我们需要在Vue使用Jinja2传递的数据,那么就需要在模板中通过数据属性的方式传递,例如: ```html <div id="app" data-message="{{ jinja2_variable }}"> {{ message }} <!-- 这里由Vue渲染,所以message是Vue的数据 --> </div> ``` 然后在app.js中: ```javascript var app = new Vue({ el: '#app', data: { message: '' // 初始化为空 }, mounted: function() { // 从DOM元素中获取Jinja2传递的数据 this.message = this.$el.getAttribute('data-message'); } }); ``` 或者更直接地,在创建Vue实例时直接使用Jinja2传递的值: ```javascript var app = new Vue({ el: '#app', data: { message: document.getElementById('app').getAttribute('data-message') } }); ``` 总结: 为了避免冲突,通常建议: 1. 尽量将前端逻辑放在外部js文件中,避免在模板中混合使用2. 对于需要由Jinja2渲染的数据,通过HTML元素的属性(如data-*)传递给Vue。 3. 如果必须在模板中写Vue的模板语法,则使用`{% raw %}``{% endraw %}`包裹,或者修改Vue的分隔符。 根据引用[5]提到的项目结构,我们可以将Vue作为前端框架独立开发,然后通过Flask的路由返回主页面,其他页面由Vue-router管理。这样前后端分离更彻底,避免了模板冲突。 因此,在PyCharm中处理FlaskVue的模板冲突,可以选择上述方法之一。根据项目需求,如果项目较小,可以修改Vue的分隔符;如果项目较大,建议采用前后端分离的方式,将Vue作为单独的SPA应用,通过Flask的静态文件服务提供。 注意:在PyCharm中,我们需要正确配置项目结构,将Vue项目构建后的输出目录设置为Flask的静态文件夹(static)模板文件夹(templates)中。通常,Vue项目构建后,会生成一个dist目录,其中包含index.htmlstatic目录。我们将index.html放入Flask的templates目录,static目录下的内容放入Flask的static目录。然后Flask的路由返回这个index.html即可。 例如: ```python from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') # 这个index.html是Vue构建后放在templates中的 ``` 这样,Vue应用就作为静态页面被Flask服务提供,完全避免了模板冲突。 以上方法可以根据实际情况选择。 </think> 在PyCharm中开发Flask项目时,Vue前端与Jinja2模板的语法冲突主要源于**双花括号`{{ }}`的解析冲突**。以下是完整的解决方案: ### 解决方法一:修改Vue的分隔符(推荐) ```javascript // 在Vue初始化时自定义分隔符 new Vue({ delimiters: ["${", "}"], // 修改为ES6模板字符串风格 // delimiters: ["[[", "]]"], // 或改为中括号风格 data: { message: "Hello Vue!" } }) ``` ```html <!-- 模板中使用新分隔符 --> <div id="app"> ${ message } <!-- 不再与Jinja2冲突 --> </div> ``` **优势**:只需修改前端配置,无需调整后端[^2][^4]。 ### 解决方法二:使用`{% raw %}`标签包裹Vue代码 ```html {% raw %} <!-- Jinja2原始内容标签 --> <div id="app"> {{ vueVariable }} <!-- 此处Vue语法不会被Jinja2解析 --> </div> {% endraw %} <!-- 外部区域仍可正常使用Jinja2 --> {{ flaskVariable }} ``` **适用场景**:局部使用Vue组件时[^2]。 ### 解决方法三:彻底前后端分离(最佳实践) 1. **项目结构调整**: ``` project/ ├── backend/ # Flask项目 │ ├── app.py │ └── requirements.txt ├── frontend/ # Vue项目(通过vue-cli创建) │ ├── src/ │ └── package.json └── docker-compose.yml ``` 2. **Flask仅提供API**: ```python # Flask路由示例 @app.route('/api/data') def get_data(): return jsonify({"key": "value"}) # 仅返回JSON数据[^2][^4] ``` 3. **Vue独立开发**: ```javascript // Vue调用API axios.get('/api/data').then(res => { this.data = res.data }) ``` 4. **部署方案**: - 开发环境:分别运行`flask run``npm run serve` - 生产环境:Vue构建`dist`目录复制到Flask静态文件夹[^5] ### 方法四:修改Jinja2分隔符(不推荐) ```python # Flask配置(慎用) app.jinja_env.variable_start_string = '{{{' app.jinja_env.variable_end_string = '}}}' ``` **缺点**:需修改所有模板文件,影响第三方库兼容性[^2]。 --- ### 方案对比 | 方法 | 复杂度 | 维护性 | 适用场景 | |------|--------|--------|----------| | 修改Vue分隔符 | ★☆☆ | 优 | 简单页面整合 | | `raw`标签包裹 | ★★☆ | 良 | 局部使用Vue | | 前后端分离 | ★★★ | 优 | 中大型项目 | | 修改Jinja2 | ★★☆ | 差 | 遗留项目改造 | > **推荐选择**:中小项目用**方法一**,复杂项目用**方法三**。PyCharm可同时打开前后端项目,使用`Run/Debug Configurations`分别配置启动命令[^5]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值